home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / mus / edit / med_3_22.lha / programmers / modplayer / modplayer.a < prev    next >
Text File  |  1992-01-12  |  58KB  |  2,112 lines

  1. ;    modplayer.a
  2. ;    ~~~~~~~~~~~
  3. ; The music player routine for MED V3.2 (and OctaMED V2.0 4-channel) songs.
  4. ; Written by Teijo Kinnunen.
  5. ; If you find bugs in this routine, please notify:
  6. ;    Teijo Kinnunen
  7. ;    Oksantie 19
  8. ;    SF-86300  OULAINEN
  9. ;    FINLAND
  10. ;
  11. ; THIS CODE MAY BE FREELY USED AND DISTRIBUTED!
  12.  
  13. ;============================================================================
  14.  
  15. MIDI    EQU    0    ;1 = include MIDI code
  16. AUDDEV    EQU    1    ;1 = allocate channels using audio.device
  17. SYNTH    EQU    1    ;1 = include synth-sound handler
  18. CHECK    EQU    1    ;1 = do range checkings (track, sample in mem etc.)
  19. RELVOL    EQU    1    ;1 = include relative volume handling code
  20. IFF53    EQU    1    ;1 = play IFF 3- and 5-octave samples correctly
  21. HOLD    EQU    1    ;1 = handle hold/decay
  22. ;****** Timing control ******
  23. VBLANK    EQU    0    ;1 = use VBlank interrupt (when absolutely necessary)
  24. CIAB    EQU    1    ;1 = use CIAB timers (default)
  25. ; Please use CIAB whenever possible to avoid problems with variable
  26. ; VBlank speeds and to allow the use of command F01 - FF0 (set tempo)
  27. ; If both are set to 0, the timing is left for you (never set both to 1!!),
  28. ; then you just call _IntHandler for each timing pulse.
  29.  
  30. ;============================================================================
  31.  
  32. ;If you are making a demo/game with only a single tune you'd like to
  33. ;incorporate in the code (like "easyplayer.a" of MED V3), set the following
  34. ;flag to 1. This requires an assembler with INCBIN (or equivalent) directive.
  35. ;You have to type the module name into the INCBIN statement (located near the
  36. ;end of this file, on line 2052).
  37.  
  38. EASY    EQU    0
  39.  
  40. ;Call _startmusic to play the music, and _endmusic to stop it (before
  41. ;exiting). Note: don't call _startmusic twice!! This would cause the module
  42. ;to be relocated twice (= Guru). If you need to stop and continue playing,
  43. ;don't use the EASY routines, use PlayModule/StopPlayer... instead.
  44.  
  45. ;============================================================================
  46.  
  47. ;the MMD0 structure offsets
  48. mmd_id        EQU    0
  49. mmd_modlen    EQU    4
  50. mmd_songinfo    EQU    8
  51. mmd_songlen    EQU    12    ;currently unused
  52. mmd_blockarr    EQU    16
  53. mmd_blockarrlen    EQU    20
  54. mmd_smplarr    EQU    24
  55. mmd_smplarrlen    EQU    28
  56. mmd_expdata    EQU    32
  57. mmd_expsize    EQU    36
  58. mmd_pstate    EQU    40 ; <0 = play song, 0 = don't play, >0 = play block
  59. mmd_pblock    EQU    42
  60. mmd_pline    EQU    44
  61. mmd_pseqnum    EQU    46
  62. mmd_actplayline    EQU    48
  63. mmd_counter    EQU    50
  64. mmd_songsleft    EQU    51
  65.  
  66. ;the MMD0song structure
  67. ;Instrument data here (504 bytes = 63 * 8)
  68. msng_numblocks    EQU    504
  69. msng_songlen    EQU    506
  70. msng_playseq    EQU    508
  71. msng_deftempo    EQU    764
  72. msng_playtransp    EQU    766
  73. msng_flags    EQU    767
  74. msng_reserved    EQU    768
  75. msng_tempo2    EQU    769
  76. msng_trkvol    EQU    770
  77. msng_mastervol    EQU    786
  78. msng_numsamples    EQU    787
  79.  
  80. ;Instrument data
  81. inst_repeat    EQU    0
  82. inst_replen    EQU    2
  83. inst_midich    EQU    4
  84. inst_midipreset    EQU    5
  85. inst_svol    EQU    6
  86. inst_strans    EQU    7
  87.  
  88. ;Audio hardware offsets
  89. ac_ptr    EQU    $00
  90. ac_len    EQU    $04
  91. ac_per    EQU    $06
  92. ac_vol    EQU    $08
  93.  
  94. ;Trackdata sizes
  95. T03SZ    EQU    88
  96. T415SZ    EQU    18
  97.  
  98.         section    "text",code
  99.  
  100.     IFNE    EASY
  101.  
  102.         xdef    _startmusic,_endmusic
  103.  
  104. _startmusic    lea    easymod,a0
  105.         bsr.w    _RelocModule
  106.         bsr.w    _InitPlayer
  107.         lea    easymod,a0
  108.         bra.w    _PlayModule
  109.  
  110. _endmusic    bra.w    _RemPlayer
  111.     ENDC
  112.  
  113.  
  114.  
  115. _ChannelOff:    ;d0 = channel #
  116.         lea    trackdataptrs(pc),a1
  117.         lsl.b    #2,d0
  118.         adda.w    d0,a1
  119.         lsr.b    #2,d0
  120.         movea.l    (a1),a1
  121.     IFNE    MIDI
  122.         move.b    trk_prevmidin(a1),d1    ;is it MIDI??
  123.         beq.s    notcomidi        ;not a MIDI note
  124. choff_midi:    clr.b    trk_prevmidin(a1)
  125.         lea    noteondata(pc),a0
  126.         move.b    d1,1(a0)
  127.         move.b    trk_prevmidich(a1),(a0)    ;prev MIDI channel
  128.         clr.b    2(a0)
  129.         or.b    #$90,(a0)        ;note off
  130.         moveq    #3,d0
  131.         bra.w    _AddMIDIData
  132.     ENDC
  133. notcomidi:    cmp.b    #4,d0
  134.         bge.s    notamigatrk
  135.     IFNE    SYNTH
  136.         clr.l    trk_synthptr(a1)
  137.         clr.b    trk_synthtype(a1)
  138.     ENDC
  139.         moveq    #1,d1
  140.         lsl.w    d0,d1
  141.         move.w    d1,$dff096
  142. notamigatrk:    rts
  143.  
  144. SoundOff:    move.l    d2,-(sp)
  145.         moveq    #15,d2
  146. SO_loop0    move.l    d2,d0
  147.         bsr.s    _ChannelOff
  148.         dbf    d2,SO_loop0
  149.         lea    _module(pc),a0
  150.         clr.l    (a0)        ;play nothing
  151.         move.l    (sp)+,d2
  152.         rts
  153.  
  154. _PlayNote:    ;d0(w) = trk #, d1 = note #, d2 = vol, d3(w) = instr # a3 = addr of instr
  155.         moveq    #0,d4
  156.         bset    d0,d4    ;d4 is mask for this channel
  157.         movea.l    mmd_smplarr(a6),a0
  158.         add.w    d3,d3            ;d3 = instr.num << 2
  159.         add.w    d3,d3
  160.         move.l    0(a0,d3.w),d5        ;get address of instrument
  161.     IFNE    MIDI
  162.         bne.s    inmem
  163.         tst.b    inst_midich(a3)        ;is MIDI channel set
  164.     ENDC
  165.     IFNE    CHECK
  166.         beq.w    pnote_rts        ; NO!!!
  167.     ENDC
  168. inmem:        add.b    msng_playtransp(a4),d1    ;add play transpose
  169.         add.b    inst_strans(a3),d1    ;and instr. transpose
  170.         cmp.b    #4,d0
  171.         bge.s    nodmaoff    ;track # >= 4: not an Amiga channel
  172.         move.l    d5,a1
  173.     IFNE    SYNTH
  174.         tst.l    d5
  175.         beq.s    stpdma
  176.         tst.b    trk_synthtype(a5)
  177.         ble.s    stpdma        ;prev. type = sample/hybrid
  178.         cmp.w    #-1,4(a1)    ;type == SYNTHETIC??
  179.         beq.s    nostpdma
  180.     ENDC
  181. stpdma:        move.w    d4,$dff096        ;stop this channel (dmacon)
  182. nostpdma:
  183.     IFNE    SYNTH
  184.         clr.l    trk_synthptr(a5)
  185.     ENDC
  186. nodmaoff:
  187.     IFNE    MIDI
  188.         move.b    trk_prevmidin(a5),d3    ;get prev. midi note
  189.         beq.s    noprevmidi
  190.         clr.b    trk_prevmidin(a5)
  191.         lea    noteondata+2(pc),a0
  192.         clr.b    (a0)                ;volume = 0
  193.         move.b    d3,-(a0)
  194.         move.b    trk_prevmidich(a5),-(a0)    ;prev midi channel
  195.         or.b    #$90,(a0)            ;note off
  196.         movem.w    d0-d1,-(sp)
  197.         moveq    #3,d0
  198.         bsr.w    _AddMIDIData
  199.         movem.w    (sp)+,d0-d1
  200. noprevmidi:    tst.b    inst_midich(a3)
  201.         bne.w    handleMIDInote
  202.     ENDC
  203.     IFNE    CHECK
  204.         cmp.w    #4,d0        ;track > 3???
  205.         bge.w    pnote_rts    ;no Amiga instruments here!!!
  206.     ENDC
  207. ; handle decay (for tracks 0 - 3 only!!)
  208.     IFNE    HOLD
  209.         clr.b    trk_fadespd(a5)        ;no fade yet..
  210.         move.b    trk_initdecay(a5),trk_decay(a5)    ;set decay
  211.     ENDC
  212.         clr.b    trk_vibroffs(a5)    ;clr vibrato offset
  213.         or.w    d4,dmaonmsk
  214.         move.l    d5,a0
  215.         subq.b    #1,d1
  216.     IFNE    SYNTH
  217.         tst.w    4(a0)
  218.         bmi.w    handleSynthnote
  219.         clr.b    trk_synthtype(a5)
  220.     ENDC
  221. tlwtst0:    tst.b    d1
  222.         bpl.s    notenot2low
  223.         add.b    #12,d1    ;note was too low, octave up
  224.         bra.s    tlwtst0
  225. notenot2low:    cmp.b    #62,d1
  226.         ble.s    endpttest
  227.         sub.b    #12,d1    ;note was too high, octave down
  228. endpttest:
  229.         moveq    #0,d4
  230.     IFNE    IFF53
  231.         move.w    4(a0),d0    ;Soitin-struct in a0
  232.         bne.s    iff5or3oct    ;note # in d1 (0 - ...)
  233.     ENDC
  234.         move.l    a0,d0
  235.         lea    _periods(pc),a0
  236.         move.l    a0,trk_periodtbl(a5)
  237.         add.b    d1,d1
  238.         move.w    0(a0,d1.w),d5 ;put period to d5
  239.         move.l    d0,a0
  240.         addq.l    #6,d0        ;Skip structure
  241.         move.l    (a0),d1        ;length
  242.         move.w    (a3),d4        ;inst_repeat
  243.         move.w    inst_replen(a3),d3
  244.     IFNE    IFF53
  245.         bra.s    end_getdata
  246. shiftcnt    dc.b    4,3,2,1,1,0,2,2,1,1,0,0
  247. mullencnt    dc.b    15,7,3,1,1,0,3,3,1,1,0,0
  248. octstart    dc.b    12,12,12,12,24,24,0,12,12,24,24,36
  249. iff5or3oct:    movem.l    d6-d7,-(sp)
  250.         moveq    #0,d7
  251.         move.w    d1,d7
  252.         divu    #12,d7    ;octave #
  253.         move.l    d7,d5
  254.         swap    d5    ;note number in this oct (0-11) is in d5
  255.         move.l    (a0),d1
  256.         cmp.b    #2,d0
  257.         bne.s    no3oct
  258.         addq.l    #6,d7
  259.         divu    #7,d1    ;get length of the 1st octave
  260.         bra.s    no5oct
  261. no3oct:        divu    #31,d1    ;get length of the 1st octave (5 octaves)
  262. no5oct:        move.l    d1,d0        ;d0 and d1 = length of the 1st oct
  263.         move.w    (a3),d4        ;inst_repeat
  264.         move.w    inst_replen(a3),d3
  265.         moveq    #0,d6
  266.         move.b    shiftcnt(pc,d7.w),d6
  267.         lsl.w    d6,d4
  268.         lsl.w    d6,d3
  269.         lsl.w    d6,d1
  270.         move.b    mullencnt(pc,d7.w),d6
  271.         mulu    d6,d0        ;offset of this oct from 1st oct
  272.         add.l    a0,d0        ;add base address to offset
  273.         addq.l    #6,d0        ;skip structure
  274.         lea    _periods(pc),a1
  275.         add.b    octstart(pc,d7.w),d5
  276.         add.b    d5,d5
  277.         move.w    0(a1,d5.w),d5
  278.         movem.l    (sp)+,d6-d7
  279.     ENDC
  280. end_getdata    movea.l    trk_audioaddr(a5),a1 ;base of this channel's regs
  281.         move.l    d0,(a1)+        ;put it in ac_ptr (= 0)
  282.         cmp.w    #1,d3
  283.         bhi.s    repeat
  284.         
  285.         move.l    #_chipzero,trk_sampleptr(a5) ;pointer of zero word
  286.         move.w    #1,trk_samplelen(a5)    ;length: 1 word
  287.         lsr.l    #1,d1            ;shift length right
  288.         move.w    d1,(a1)+    ;and put to custom chip (ac_len)
  289.         bra.s    retsn1
  290.  
  291. repeat:        tst.w    d4
  292.         beq.s    begin0        ;rep. start < 2
  293.         move.w    d4,(a1)+    ;move repeat to hardware
  294.         bra.s    beginn0
  295. begin0:        move.w    d3,(a1)+    ;ac_len
  296. beginn0:    add.l    d4,d4        ;shift
  297.         add.l    d4,d0        ;d0 = starting address of repeat
  298.         move.l    d0,trk_sampleptr(a5)    ;remember rep. start
  299.         move.w    d3,trk_samplelen(a5)    ;remember rep. length
  300.                 
  301. retsn1:        move.w    d5,(a1)+ ;getinsdata puts period to d5 (a1 = ac_per)
  302.         move.w    d2,(a1)    ;a1 = ac_vol
  303.         move.w    d5,trk_prevper(a5)
  304.     IFNE    SYNTH
  305.         tst.b    trk_synthtype(a5)
  306.         bne.w    hSn2
  307.     ENDC
  308. pnote_rts    rts
  309.  
  310.     IFNE    MIDI
  311. handleMIDInote:    add.b    #23,d1        ;2 octaves higher and -1
  312.         bpl.s    hmn_not2low    ;note number not too low
  313. hmn_2low    add.b    #12,d1        ;it was too low, 1 octave up
  314.         bmi.s    hmn_2low
  315. hmn_not2low
  316.         add.b    d2,d2        ;volume 0 - 63 => 0 - 127
  317.         subq.b    #1,d2        ;if 128 => 127
  318.         bpl.s    hmn_notvolu0
  319.         moveq    #0,d2
  320. hmn_notvolu0
  321.         moveq    #0,d5
  322.         move.b    inst_midich(a3),d5    ;get midi chan of this instrument
  323.         bpl.s    hmn_nosmof    ;bit 7 clear
  324.         clr.b    trk_prevmidin(a5)    ;suppress note off!
  325.         and.b    #$1F,d5        ;clear all flag bits etc...
  326.         bra.s    hmn_smof
  327. hmn_nosmof    move.b    d1,trk_prevmidin(a5)
  328. hmn_smof    subq.b    #1,d5        ;from 1-16 to 0-15
  329.         move.b    d5,trk_prevmidich(a5)    ;save to prev midi channel
  330.  
  331.         move.b    inst_midipreset(a3),d0    ;get preset #
  332.         beq.s    nochgpres    ;zero = no preset
  333.         cmp.b    prevmidicpres(pc,d5.w),d0    ;is this previous preset ??
  334.         beq.s    nochgpres    ;yes...no need to change
  335.         lea    prevmidicpres(pc,d5.w),a1
  336.         move.b    d0,(a1)        ;save preset to prevmidicpres
  337.         subq.b    #1,d0        ;sub 1 to get 0 - 127
  338.         lea    preschgdata+1(pc),a0
  339.         move.b    d0,(a0)        ;push the number to second byte
  340.         move.b    #$c0,-(a0)    ;command: $C
  341.         or.b    d5,(a0)        ;"or" midi channel
  342.         moveq    #2,d0
  343.         move.w    d1,-(sp)
  344.         bsr.w    _AddMIDIData
  345.         move.w    (sp)+,d1
  346.         tst.b    d2
  347.         beq.s    hmn_suppress    ;vol = 0, don't send NOTE ON
  348.  
  349. nochgpres    lea    bytesinnotebuff(pc),a0
  350.         movea.l    a0,a1
  351.         adda.w    (a0)+,a0
  352.         or.b    #$90,d5        ;MIDI: Note on
  353.         move.b    d5,(a0)+    ;MIDI msg Note on & channel
  354.         move.b    d1,(a0)+    ;MIDI msg note #
  355.         move.b    d2,(a0)        ;MIDI msg volume
  356.         beq.s    hmn_suppress    ;vol = 0 -> no note
  357.         addq.w    #3,(a1)
  358.         rts
  359. hmn_suppress    clr.b    trk_prevmidin(a5)
  360.         rts
  361.  
  362. prevmidicpres:    dc.l    0,0,0,0 ; 16 bytes
  363.     ENDC
  364.  
  365.     IFNE    SYNTH
  366. handleSynthnote:
  367.         move.b    d1,trk_prevnote2(a5)
  368.         move.l    a0,trk_synthptr(a5)
  369.         cmp.w    #-2,4(a0)    ;HYBRID??
  370.         bne.s    hSn_nossn
  371.         st    trk_synthtype(a5)
  372.         movea.l    278(a0),a0    ;yep, get the waveform pointer
  373.         bra.w    tlwtst0        ;go and play it
  374. hSn_nossn:    move.b    #1,trk_synthtype(a5)
  375.         lea    _synthper(pc),a1
  376.         move.l    a1,trk_periodtbl(a5) ;save table ptr for synth periods
  377.         add.w    d1,d1
  378.         move.w    0(a1,d1.w),d1
  379.         movea.l    trk_audioaddr(a5),a1
  380.         move.w    d1,trk_prevper(a5)
  381.         move.w    d1,ac_per(a1)
  382.         clr.l    trk_sampleptr(a5)
  383. hSn2:        lea    trk_arpgoffs(a5),a1
  384.         clr.l    (a1)+
  385.         clr.l    (a1)+
  386.         clr.l    (a1)+
  387.         clr.l    (a1)+
  388.         clr.l    (a1)+
  389.         clr.l    (a1)+
  390.         move.l    #sinetable,(a1)+
  391.         clr.w    (a1)+
  392.         movea.l    trk_synthptr(a5),a0
  393.                 move.w    18(a0),(a1)+
  394.                 clr.b    (a1)
  395.                 cmp.b    #$E,trk_cmd(a5)
  396.                 bne.s    synth_start
  397.                 move.b    trk_cmdqual(a5),trk_wfcmd+1(a5)
  398.  
  399. synth_start:    move.l    a3,-(sp)
  400.         movea.l    trk_audioaddr(a5),a3    ;audio channel base address
  401.         subq.b    #1,trk_volxcnt(a5)    ;decrease execute counter..
  402.         bgt.w    synth_wftbl        ;not 0...go to waveform
  403.         move.b    trk_initvolxspd(a5),trk_volxcnt(a5) ;reset counter
  404.         move.b    trk_volchgspd(a5),d0    ;volume change??
  405.         beq.s    synth_nochgvol        ;no.
  406.         add.b    trk_synvol(a5),d0    ;add previous volume
  407.         bpl.s    synth_voln2l        ;not negative
  408.         moveq    #0,d0            ;was negative => 0
  409. synth_voln2l:    cmp.b    #$40,d0            ;too high??
  410.         ble.s    synth_voln2h        ;not 2 high.
  411.         moveq    #$40,d0            ;was 2 high => 64
  412. synth_voln2h:    move.b    d0,trk_synvol(a5)    ;remember new...
  413.         move.b    d0,ac_vol+1(a3)        ;and change it
  414. synth_nochgvol:    move.l    trk_envptr(a5),d1    ;envelope pointer
  415.         beq.s    synth_novolenv
  416.         movea.l    d1,a1
  417.         move.b    (a1)+,d0
  418.         add.b    #128,d0
  419.         lsr.b    #2,d0
  420.         move.b    d0,trk_synvol(a5)
  421.         move.b    d0,ac_vol+1(a3)
  422.         addq.b    #1,trk_envcount(a5)
  423.         bpl.s    synth_endenv
  424.         clr.b    trk_envcount(a5)
  425.         move.l    trk_envrestart(a5),a1
  426. synth_endenv    move.l    a1,trk_envptr(a5)
  427. synth_novolenv    move.w    trk_volcmd(a5),d0    ;get table position ptr
  428.         tst.b    trk_volwait(a5)        ;WAI(t) active
  429.         beq.s    synth_getvolcmd        ;no
  430.         subq.b    #1,trk_volwait(a5)    ;yep, decr wait ctr
  431.         ble.s    synth_getvolcmd        ;0 => continue
  432.         bra.w    synth_wftbl        ;> 0 => still wait
  433. synth_inccnt:    addq.b    #1,d0
  434. synth_getvolcmd:
  435.         addq.b    #1,d0            ;advance pointer
  436.         move.b    21(a0,d0.w),d1        ;get command
  437.         bmi.s    synth_cmd        ;negative = command
  438.         move.b    d1,trk_synvol(a5)    ;set synthvol
  439.         move.b    d1,ac_vol+1(a3)        ;change it!!
  440.         bra.w    synth_endvol        ;end of volume executing
  441. synth_cmd:    and.w    #$000f,d1
  442.         add.b    d1,d1
  443.         move.w    synth_vtbl(pc,d1.w),d1
  444.         jmp    syv(pc,d1.w)
  445. synth_vtbl:    dc.w    syv_f0-syv,syv_f1-syv,syv_f2-syv,syv_f3-syv
  446.         dc.w    syv_f4-syv,syv_f5-syv,syv_f6-syv
  447.         dc.w    synth_endvol-syv,synth_endvol-syv,synth_endvol-syv
  448.         dc.w    syv_fa-syv,syv_ff-syv,synth_endvol-syv
  449.         dc.w    synth_endvol-syv,syv_fe-syv,syv_ff-syv
  450. syv:
  451. syv_fe:        move.b    22(a0,d0.w),d0        ;JMP
  452.         bra.s    synth_getvolcmd
  453. syv_f0:        move.b    22(a0,d0.w),trk_initvolxspd(a5) ;change volume ex. speed
  454.         bra.s    synth_inccnt
  455. syv_f1:        move.b    22(a0,d0.w),trk_volwait(a5)    ;WAI(t)
  456.         addq.b    #1,d0
  457.         bra.s    synth_endvol
  458. syv_f3:        move.b    22(a0,d0.w),trk_volchgspd(a5) ;set volume slide up
  459.         bra.s    synth_inccnt
  460. syv_f2:        move.b    22(a0,d0.w),d1
  461.         neg.b    d1
  462.         move.b    d1,trk_volchgspd(a5) ;set volume slide down
  463.         bra.s    synth_inccnt
  464. syv_fa:        move.b    22(a0,d0.w),trk_wfcmd+1(a5) ;JWS (jump wform sequence)
  465.         clr.b    trk_wfwait(a5)
  466.         bra.s    synth_inccnt
  467. syv_f4:        move.b    22(a0,d0.w),d1
  468.         bsr.s    synth_getwf
  469.         clr.l    trk_envrestart(a5)
  470. syv_f4end    move.l    a1,trk_envptr(a5)
  471.         clr.b    trk_envcount(a5)
  472.         bra.w    synth_inccnt
  473. syv_f5:        move.b    22(a0,d0.w),d1
  474.         bsr.s    synth_getwf
  475.         move.l    a1,trk_envrestart(a5)
  476.         bra.s    syv_f4end
  477. syv_f6        clr.l    trk_envptr(a5)
  478.         bra.w    synth_getvolcmd
  479. synth_getwf    ext.w    d1    ;d1 = wform number, returns ptr in a1
  480.         add.w    d1,d1    ;create index
  481.         add.w    d1,d1
  482.         lea    278(a0),a1
  483.         adda.w    d1,a1
  484.         movea.l    (a1),a1        ;get wform address
  485.         addq.l    #2,a1        ;skip length
  486.         rts
  487. syv_ff:        subq.b    #1,d0
  488. synth_endvol:    move.w    d0,trk_volcmd(a5)
  489. synth_wftbl:    move.b    trk_synvol(a5),trk_prevvol(a5)
  490.         adda.w    #158,a0
  491.         subq.b    #1,trk_wfxcnt(a5)    ;decr. wf speed counter
  492.         bgt.w    synth_arpeggio        ;not yet...
  493.         move.b    trk_initwfxspd(a5),trk_wfxcnt(a5) ;restore speed counter
  494.         move.w    trk_wfcmd(a5),d0    ;get table pos offset
  495.         move.w    trk_wfchgspd(a5),d1    ;CHU/CHD ??
  496.         beq.s    synth_tstwfwai        ;0 = no change
  497. wytanwet:    add.w    trk_perchg(a5),d1    ;add value to current change
  498.         move.w    d1,trk_perchg(a5)    ;remember amount of change
  499.         add.w    trk_prevper(a5),d1    ;add initial period to it
  500.         cmp.w    #113,d1            ;overflow??
  501.         bge.s    synth_pern2h
  502.         moveq    #113,d1
  503. synth_pern2h:    move.w    d1,ac_per(a3)        ;push the changed period
  504. synth_tstwfwai:    tst.b    trk_wfwait(a5)        ;WAI ??
  505.         beq.s    synth_getwfcmd        ;not waiting...
  506.         subq.b    #1,trk_wfwait(a5)    ;decr wait counter
  507.         beq.s    synth_getwfcmd        ;waiting finished
  508.         bra.w    synth_arpeggio        ;still sleep...
  509. synth_incwfc:    addq.b    #1,d0
  510. synth_getwfcmd:    addq.b    #1,d0            ;advance position counter
  511.         move.b    -9(a0,d0.w),d1        ;get command
  512.         bmi.s    synth_wfcmd        ;negative = command
  513.         ext.w    d1
  514.         add.w    d1,d1
  515.         add.w    d1,d1
  516.         movea.l    120(a0,d1.w),a1
  517.         move.w    (a1)+,ac_len(a3)    ;push waveform length
  518.         move.l    a1,(a3)         ;and the new pointer (0 = ac_ptr)
  519.         bra.w    synth_wfend        ;no new commands now...
  520. synth_wfcmd:    and.w    #$000f,d1        ;get the right nibble
  521.         add.b    d1,d1            ;* 2
  522.         move.w    synth_wfctbl(pc,d1.w),d1
  523.         jmp    syw(pc,d1.w)        ;jump to command
  524. synth_wfctbl:    dc.w    syw_f0-syw,syw_f1-syw,syw_f2-syw,syw_f3-syw,syw_f4-syw
  525.         dc.w    syw_f5-syw,syw_f6-syw,syw_f7-syw,synth_wfend-syw
  526.         dc.w    synth_wfend-syw,syw_fa-syw,syw_ff-syw
  527.         dc.w    syw_fc-syw,synth_getwfcmd-syw,syw_fe-syw,syw_ff-syw
  528. syw:
  529. syw_f7:        move.b    -8(a0,d0.w),d1
  530.         ext.w    d1
  531.         add.w    d1,d1
  532.         add.w    d1,d1
  533.         movea.l    120(a0,d1.w),a1
  534.         addq.l    #2,a1
  535.         move.l    a1,trk_synvibwf(a5)
  536.         bra.s    synth_incwfc
  537. syw_fe:        move.b    -8(a0,d0.w),d0        ;jump (JMP)
  538.         bra.s    synth_getwfcmd
  539. syw_fc:        move.w    d0,trk_arpsoffs(a5)    ;new arpeggio begin
  540.         move.w    d0,trk_arpgoffs(a5)
  541. synth_findare:    addq.b    #1,d0
  542.         tst.b    -9(a0,d0.w)
  543.         bpl.s    synth_findare
  544.         bra.s    synth_getwfcmd
  545. syw_f0:        move.b    -8(a0,d0.w),trk_initwfxspd(a5)    ;new waveform speed
  546.         bra    synth_incwfc
  547. syw_f1:        move.b    -8(a0,d0.w),trk_wfwait(a5)    ;wait waveform
  548.         addq.b    #1,d0
  549.         bra.s    synth_wfend
  550. syw_f4:        move.b    -8(a0,d0.w),trk_synvibdep+1(a5)    ;set vibrato depth
  551.         bra.w    synth_incwfc
  552. syw_f5:        move.b    -8(a0,d0.w),trk_synthvibspd+1(a5) ;set vibrato speed
  553.         addq.b    #1,trk_synthvibspd+1(a5)
  554.         bra.w    synth_incwfc
  555. syw_f2:        moveq    #0,d1            ;set slide down
  556.         move.b    -8(a0,d0.w),d1
  557. synth_setsld:    move.w    d1,trk_wfchgspd(a5)
  558.         bra.w    synth_incwfc
  559. syw_f3:        move.b    -8(a0,d0.w),d1        ;set slide up
  560.         neg.b    d1
  561.         ext.w    d1
  562.         bra.s    synth_setsld
  563. syw_f6:        clr.w    trk_perchg(a5)        ;reset period
  564.         move.w    trk_prevper(a5),ac_per(a3)
  565.         bra.w    synth_getwfcmd
  566. syw_fa:        move.b    -8(a0,d0.w),trk_volcmd+1(a5) ;JVS (jump volume sequence)
  567.         clr.b    trk_volwait(a5)
  568.         bra.w    synth_incwfc
  569. syw_ff:        subq.b    #1,d0        ;pointer = END - 1
  570. synth_wfend:    move.w    d0,trk_wfcmd(a5)
  571. synth_arpeggio:    move.w    trk_arpgoffs(a5),d0
  572.         beq.s    synth_vibrato
  573.         moveq    #0,d1
  574.         move.b    -8(a0,d0.w),d1
  575.         add.b    trk_prevnote2(a5),d1
  576.         movea.l    trk_periodtbl(a5),a1    ;get period table
  577.         add.w    d1,d1
  578.         move.w    0(a1,d1.w),d1
  579.         add.w    trk_perchg(a5),d1
  580.         move.w    d1,trk_prevper(a5)
  581.         move.w    d1,ac_per(a3)
  582.         addq.b    #1,d0
  583.         tst.b    -8(a0,d0.w)
  584.         bpl.s    synth_noarpres
  585.         move.w    trk_arpsoffs(a5),d0
  586. synth_noarpres:    move.w    d0,trk_arpgoffs(a5)
  587. synth_vibrato:    move.w    trk_synvibdep(a5),d1    ;get vibrato depth
  588.         beq.s    synth_rts        ;0 => no vibrato
  589.         move.w    trk_synviboffs(a5),d0    ;get offset
  590.         lsr.w    #4,d0            ;/ 16
  591.         and.w    #$1f,d0            ;sinetable offset (0-31)
  592.         movea.l trk_synvibwf(a5),a0
  593.         move.b    0(a0,d0.w),d0       ;get a byte
  594.         ext.w    d0            ;to word
  595.         muls    d1,d0            ;amplify (* depth)
  596.         asr.w    #8,d0            ;and divide by 64
  597.         move.w    trk_prevper(a5),d1    ;get the old period
  598.         add.w    d0,d1            ;add vibrato...
  599.         add.w    trk_perchg(a5),d1    ;and pitch change...
  600.         move.w    d1,ac_per(a3)        ;change.
  601.         move.w    trk_synthvibspd(a5),d0    ;vibrato speed
  602.         add.w    d0,trk_synviboffs(a5)    ;add to offset
  603. synth_rts:    move.l    (sp)+,a3
  604.         rts
  605.     ENDC
  606. sinetable:    dc.b    0,25,49,71,90,106,117,125,127,125,117,106,90,71,49
  607.         dc.b    25,0,-25,-49,-71,-90,-106,-117,-125,-127,-125,-117
  608.         dc.b    -106,-90,-71,-49,-25,0
  609.  
  610. _Wait1line:    move.l    d0,-(sp)    ;d1 = vsync counters to wait - 1
  611. wl0:        move.b    $dff007,d0
  612. wl1:        cmp.b    $dff007,d0
  613.         beq.s    wl1
  614.         dbf    d1,wl0
  615.         move.l    (sp)+,d0
  616.         rts
  617. pushnewvals:    movea.l    (a1)+,a5
  618.         lsr.b    #1,d0
  619.         bcc.s    rpnewv
  620.         move.l    trk_sampleptr(a5),d1
  621.         beq.s    rpnewv
  622.         movea.l    trk_audioaddr(a5),a0
  623.         move.l    d1,(a0)+        ;0 = ac_ptr
  624.         move.w    trk_samplelen(a5),(a0)    ;4 = ac_len
  625. rpnewv:        rts
  626. _StartDMA:        ;This small routine turns on audio DMA
  627.         move.w    dmaonmsk(pc),d0    ;dmaonmsk contains the mask of
  628.     IFNE MIDI
  629.         beq.s    sdma_nodmaon    ;the channels that must be turned on
  630.     ENDC
  631.     IFEQ MIDI
  632.         beq.s    rpnewv
  633.     ENDC
  634.         bset    #15,d0    ;DMAF_SETCLR: set these bits in dmacon
  635.         moveq    #80,d1
  636.     IFNE    SYNTH
  637.         add.w    d1,d1    ;sometimes double wait time is required
  638.     ENDC
  639.         bsr.s    _Wait1line
  640.         move.w    d0,$dff096    ;do that!!!
  641.         moveq    #79,d1
  642.         bsr.s    _Wait1line
  643.         lea    trackdataptrs(pc),a1
  644.         bsr.s    pushnewvals
  645.         bsr.s    pushnewvals
  646.         bsr.s    pushnewvals
  647.     IFNE MIDI
  648.         bsr.s    pushnewvals
  649. sdma_nodmaon    lea    bytesinnotebuff(pc),a0
  650.         move.w    (a0)+,d0
  651.         beq.s    rpnewv
  652.         bra.w    _AddMIDIData
  653.     ENDC
  654.     IFEQ MIDI
  655.         bra.s    pushnewvals
  656.     ENDC
  657.  
  658.     IFNE MIDI
  659. prevmidipbend:    dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  660.         dc.w    $2000,$2000,$2000,$2000,$2000,$2000,$2000,$2000
  661.     ENDC
  662. ; TRACK-data structures (see definitions at the end of this file)
  663. t03d:        ds.b    20
  664.         dc.l    $dff0a0
  665.         ds.b    64+20
  666.         dc.l    $dff0b0
  667.         ds.b    64+20
  668.         dc.l    $dff0c0
  669.         ds.b    64+20
  670.         dc.l    $dff0d0
  671.         ds.b    64
  672. t415d:        ds.b    4*T415SZ
  673. t815d:        ds.b    8*T415SZ    ;8 bytes * 12 tracks = 96 bytes
  674. trackdataptrs:    dc.l    t03d,t03d+T03SZ,t03d+2*T03SZ,t03d+3*T03SZ
  675.         dc.l    t415d,t415d+T415SZ,t415d+2*T415SZ,t415d+3*T415SZ
  676.         dc.l    t815d,t815d+T415SZ,t815d+2*T415SZ,t815d+3*T415SZ
  677.         dc.l    t815d+4*T415SZ,t815d+5*T415SZ,t815d+6*T415SZ
  678.         dc.l    t815d+7*T415SZ
  679. numtracks:    dc.w    0
  680. numlines:    dc.w    0
  681. nextblock:    dc.b    0,0
  682.  
  683.  
  684. _IntHandler:    movem.l    d2-d7/a2-a5,-(sp)
  685.         movea.l    _module(pc),a6    ;a6 = pointer of MMD0
  686.         move.l    a6,d0
  687.         beq.w    plr_exit
  688.         tst.w    mmd_pstate(a6)
  689.         beq.w    plr_exit
  690.     IFNE    MIDI
  691.         clr.l    dmaonmsk
  692.     ENDC
  693.     IFEQ    MIDI
  694.         clr.w    dmaonmsk
  695.     ENDC
  696.         movea.l    mmd_songinfo(a6),a4
  697.         move.l    a4,d0
  698.         beq.w    plr_exit
  699.         moveq    #0,d3
  700.         move.b    mmd_counter(a6),d3
  701.         addq.b    #1,d3
  702.         cmp.b    msng_tempo2(a4),d3
  703.         bge.s    plr_pnewnote    ;play new note
  704.         move.b    d3,mmd_counter(a6)
  705.         bne.w    nonewnote    ;do just fx
  706. ; --- new note!! first get address of current block
  707. plr_pnewnote:    clr.b    mmd_counter(a6)
  708. ; --- now start to play it
  709.         move.w    mmd_pblock(a6),d0
  710.         movea.l    mmd_blockarr(a6),a0
  711.         add.w    d0,d0
  712.         add.w    d0,d0
  713.         movea.l    0(a0,d0.w),a2    ;block...
  714.         move.b    (a2)+,numtracks+1
  715.         move.b    (a2)+,numlines+1
  716.         move.w    mmd_pline(a6),d0
  717.         move.w    d0,d1
  718.         add.w    d0,d0    ;d0 * 2
  719.         add.w    d1,d0    ;+ d0 = d0 * 3
  720.         mulu    numtracks(pc),d0
  721.         adda.w    d0,a2        ;a2 => pointer of curr. note
  722.         moveq    #0,d7        ;number of track
  723.         pea    trackdataptrs(pc)
  724. plr_loop0:    moveq    #0,d5
  725.         move.l    (sp),a1
  726.         movea.l    (a1)+,a5    ;get address of this track's struct
  727.         move.l    a1,(sp)
  728. ; ---------------- get the note numbers
  729.         move.b    (a2)+,d5    ;get the number of this note
  730.         move.b    (a2)+,d6    ;and the 4 numbers containing fx
  731.         move.b    (a2)+,trk_cmdqual(a5)    ;get & save the fx numbers
  732. ; ---------------- clear some instrument # flags
  733.         moveq    #0,d4        ;d4 is a flag: if set, instr. is
  734.         moveq    #0,d3        ;in range G-V. If clr, it's 1-F.
  735. ; ---------------- and set them, if needed
  736.         bclr    #7,d5        ;d3 is also a flag. If it's set,
  737.         sne    d4        ;the instr. is in range 10 - 1V
  738.         bclr    #6,d5
  739.         sne    d3
  740. ; ---------------- check if there's an instrument number
  741.         move.b    d6,d0
  742.         and.w    #$f0,d0        ;d0 now contains only the # of instr
  743.         bne.s    instnum        ;instrument number is not 0
  744.         tst.b    d4        ;maybe it's G (instr. #0, d4 set)
  745.         bne.s    instnum        ;yes, it really was G!!
  746.         tst.b    d3
  747.         beq.s    noinstnum    ;it wasn't 10 - 1V either..
  748. ; ---------------- if there was, get it
  749. instnum:    lsr.b    #4,d0        ;shift it right to get number 0-F
  750.         tst.b    d4
  751.         beq.s    nogtov2
  752.         add.w    #16,d0        ;if G-V, add 16 to the number
  753. nogtov2:    tst.b    d3
  754.         beq.s    no10to1v
  755.         add.w    #32,d0
  756. ; ---------------- finally, save the number
  757. no10to1v:    subq.b    #1,d0
  758.         move.b    d0,trk_previnstr(a5) ;remember instr. number!
  759.     IFNE    HOLD
  760. ; ---------------- remember hold/decay values
  761.         lea    holdvals(pc),a0
  762.         move.b    0(a0,d0.w),trk_inithold(a5)
  763.         move.b    63(a0,d0.w),trk_initdecay(a5)
  764.     ENDC
  765. ; ---------------- get the pointer of data's of this sample in Song-struct
  766.         asl.w    #3,d0
  767.         lea    0(a4,d0.w),a3    ;a3 contains now address of it
  768.         move.l    a3,trk_previnstra(a5)
  769.         moveq    #0,d0
  770. ; ---------------- get volume and make it relative (1 - 100 %)
  771.     IFNE    RELVOL
  772.         move.b    inst_svol(a3),d0
  773.         mulu    trk_trackvol(a5),d0
  774.         lsr.w    #8,d0
  775.         move.b    d0,trk_prevvol(a5) ;vol of this instr
  776.     ENDC
  777.     IFEQ    RELVOL
  778.         move.b    inst_svol(a3),trk_prevvol(a5)
  779.     ENDC
  780. ; ---------------- remember transpose
  781.         move.b    inst_strans(a3),trk_stransp(a5)
  782. ; ---------------- check the commands
  783. noinstnum    and.b    #$0f,d6        ;now check only the effect part
  784.         move.b    d6,trk_cmd(a5)    ;save the effect number
  785.         beq.w    plr_nocmd    ;no effect
  786.         move.b    d6,d0
  787.         move.b    trk_cmdqual(a5),d6    ;get qualifier...
  788. ; ---------------- there was a command (effect), but which one??
  789.         cmp.b    #$0f,d0        ;yes effect...is it Tempo???
  790.         bne.w    not0f        ;not Tempo
  791. ; ---------------- it was tempo (F)
  792.         tst.b    d6        ;test effect qual..
  793.         beq.s    fx0fchgblck    ;if effect qualifier (last 2 #'s)..
  794.         cmp.b    #$f0,d6        ;..is zero, go to next block
  795.         bhi.s    fx0fspecial    ;if it's F1-FF something special
  796. ; ---------------- just an ordinary "change tempo"-request
  797.     IFNE    CIAB
  798.         moveq    #0,d0        ;will happen!!!
  799.         move.b    d6,d0
  800.         bsr    _SetTempo    ;change The Tempo
  801.         move.b    d6,msng_deftempo(a4)
  802.     ENDC
  803.         bra.w    plr_nocmd
  804. ; ---------------- it was FFx
  805. fx0fspecial:    cmp.b    #$f2,d6
  806.         bne.s    isfxfe
  807. ; ---------------- it was FF2, nothing to do now
  808.         move.b    d5,(a5)
  809.         moveq    #0,d5
  810.         bra.w    plr_nocmd
  811. isfxfe:        cmp.b    #$fe,d6
  812.         bne.s    notcmdfe
  813. ; ---------------- it was FFE, stop playing
  814.         clr.w    mmd_pstate(a6)
  815.     IFNE    CIAB
  816.         movea.l    craddr(pc),a0
  817.         bclr    #0,(a0)
  818.     ENDC
  819.         bsr.w    SoundOff
  820.         addq.l    #4,sp
  821.         bra.w    plr_exit
  822. notcmdfe:    cmp.b    #$fd,d6 ;change period
  823.         bne.s    isfxff
  824. ; ---------------- FFD, change the period, don't replay the note
  825.     IFNE    CHECK
  826.         cmp.w    #4,d7 ;no tracks 4 - 15
  827.         bge.w    plr_nocmd
  828.     ENDC
  829.         movea.l    trk_periodtbl(a5),a0    ;period table
  830.         subq.b    #1,d5    ;sub 1 to make "real" note number
  831.         bmi.w    plr_endloop0    ;under zero, do nothing
  832.         add.b    d5,d5
  833.         move.w    0(a0,d5.w),d0 ;get the period
  834.         movea.l    trk_audioaddr(a5),a0
  835.         move.w    d0,ac_per(a0) ;push the period
  836.         moveq    #0,d5 ;and clear it so that it won't be replayed
  837.         bra.w    plr_nocmd    ;done!!
  838. isfxff:        cmp.b    #$ff,d6        ;note off??
  839.         bne.w    plr_nocmd
  840.         move.w    d7,d0
  841.         bsr.w    _ChannelOff
  842.         bra.w    plr_nocmd
  843. ; ---------------- F00, called Pattern Break in ST
  844. fx0fchgblck:    addq.b    #1,nextblock    ;next block... (F00)
  845.         bra.w    plr_nocmd
  846. ; ---------------- was not Fxx, then it's something else!!
  847. not0f:        cmp.b    #$0e,d0
  848.         bne.s    not0e
  849.         cmp.b    #4,d7
  850.         bge.w    plr_nocmd
  851.         move.b    d6,trk_wfcmd+1(a5) ;set waveform command position ptr
  852.         bra.w    plr_nocmd
  853. not0e:        cmp.b    #$0c,d0        ;new volume???
  854.         bne.s    not0c        ;NO
  855. ; ---------------- change volume
  856.         move.b    d6,d0
  857.         bpl.s    plr_nosetdefvol
  858.         and.b    #$7F,d0
  859.     IFNE    CHECK
  860.         cmp.b    #64,d0
  861.         bgt.s    go_nocmd
  862.     ENDC
  863.         moveq    #0,d1
  864.         move.b    trk_previnstr(a5),d1
  865.         asl.w    #3,d1
  866.         move.b    d0,inst_svol(a4,d1.w)    ;set new svol
  867.         bra.s    plr_setvol
  868. plr_nosetdefvol    btst    #4,msng_flags(a4)    ;look at flags
  869.         bne.s    volhex
  870.         lsr.b    #4,d0        ;get number from left
  871.         mulu    #10,d0        ;number of tens
  872.         move.b    d6,d1        ;get again
  873.         and.b    #$0f,d1        ;this time don't get tens
  874.         add.b    d1,d0        ;add them
  875. volhex:
  876.     IFNE    CHECK
  877.         cmp.b    #64,d0
  878.         bhi.s    go_nocmd
  879.     ENDC
  880. plr_setvol
  881.     IFNE    RELVOL
  882.         mulu    trk_trackvol(a5),d0
  883.         lsr.w    #8,d0
  884.     ENDC
  885.         move.b    d0,trk_prevvol(a5)
  886. go_nocmd    bra.w    plr_nocmd
  887. ; ---------------- tempo2 change??
  888. not0c:        cmp.b    #$09,d0
  889.         bne.s    not09
  890.     IFNE    CHECK
  891.         and.b    #$1F,d6
  892.         bne.s    fx9chk
  893.         moveq    #$20,d6
  894.     ENDC
  895. fx9chk:        move.b    d6,msng_tempo2(a4)
  896.         bra.s    plr_nocmd
  897. ; ---------------- note off time set??
  898.     IFNE    HOLD
  899. not09:        cmp.b    #$08,d0
  900.         bne.s    not08
  901.         move.b    d6,d0
  902.         lsr.b    #4,d6        ;extract left  nibble
  903.         and.b    #$0f,d0        ; "   "  right  "  "
  904.         move.b    d6,trk_initdecay(a5)    ;left = decay
  905.         move.b    d0,trk_inithold(a5)    ;right = hold
  906.         bra.s    plr_nocmd
  907.     ENDC
  908.     IFEQ    HOLD
  909. not09
  910.     ENDC
  911. ; ---------------- cmd Bxx, "position jump", like Goto, yäk!!
  912. not08:        cmp.b    #$0b,d0
  913.         bne.s    not0b
  914.         move.w    d6,d0
  915.         and.w    #$00ff,d0
  916.     IFNE    CHECK
  917.         cmp.w    msng_songlen(a4),d0    ;test the song length
  918.         bhi.s    plr_nocmd
  919.     ENDC
  920.         move.w    d0,mmd_pseqnum(a6)
  921.         st    nextblock    ; = -1
  922.         bra.s    plr_nocmd
  923. ; ---------------- try portamento (3)
  924. not0b:        cmp.b    #$03,d0
  925.         bne.s    plr_nocmd
  926.         subq.b    #1,d5        ;subtract note number
  927.         bpl.s    plr_fx3note    ;there's a note...
  928.         tst.b    d6        ;qual??
  929.         beq.s    plr_endloop0    ;0 -> do nothing
  930.         bra.s    plr_setfx3spd    ;not 0 -> set new speed
  931. plr_fx3note:
  932.     IFNE    CHECK
  933.         cmp.w    #4,d7
  934.         bge.s    plr_endloop0    ;hey, what are you trying to do??
  935.     ENDC
  936.         movea.l    trk_periodtbl(a5),a0
  937.         add.b    msng_playtransp(a4),d5    ;play transpose
  938.         add.b    trk_stransp(a5),d5 ;and instrument transpose
  939.         bmi.s    plr_endloop0    ;again.. too low
  940.         add.w    d5,d5
  941.         move.w    0(a0,d5.w),trk_porttrgper(a5) ;period of this note is the target
  942. plr_setfx3spd:    move.b    d6,trk_prevportspd(a5)    ;remember size
  943.         moveq    #0,d5    ;don't play this one
  944. ; ---------------- everything is checked now: play or not to play??
  945. plr_nocmd:    tst.b    d5    ;Now we'll check if we have to play a note
  946.         beq.s    plr_endloop0    ;no.
  947. ; ---------------- we decided to play
  948.         move.b    d5,(a5)
  949.         move.w    d7,d0
  950.         move.w    d5,d1
  951.         moveq    #0,d2
  952.         move.b    trk_prevvol(a5),d2    ;get volume
  953.         moveq    #0,d3
  954.         move.b    trk_previnstr(a5),d3    ;instr #
  955.         movea.l    trk_previnstra(a5),a3    ;instr data address
  956. ; ---------------- does this instrument have holding??
  957.     IFNE    HOLD
  958.         move.b    trk_inithold(a5),trk_noteoffcnt(a5) ;initialize hold
  959.         bne.s    plr_holdok    ;not 0 -> OK
  960.         st    trk_noteoffcnt(a5)    ;0 -> hold = 0xff (-1)
  961.     ENDC
  962. ; ---------------- and finally:
  963. plr_holdok:    bsr    _PlayNote    ;play it!!!!!!!!!!!
  964. ; ---------------- end of loop: handle next track, or quit
  965. plr_endloop0:    addq.b    #1,d7
  966.         cmp.w    numtracks(pc),d7
  967.         blt.w    plr_loop0
  968.         addq.l    #4,sp        ;trackdataptrs
  969.  
  970. ; and advance song pointers
  971.         lea    nextblock(pc),a2
  972.         move.w    mmd_pline(a6),d1    ;pline
  973.         addq.w    #1,d1            ;advance line
  974.         cmp.w    numlines(pc),d1        ;advance block?
  975.         bgt.s    plr_chgblock        ;yes
  976.         tst.b    (a2)            ;command F00 ??
  977.         beq.s    plr_nochgblock        ;no, don't change block
  978. plr_chgblock:    moveq    #0,d1            ;clear the line number
  979.         tst.w    mmd_pstate(a6)        ;play block or play song
  980.         bpl.s    plr_nonewseq        ;play block only...
  981.         move.w    mmd_pseqnum(a6),d0    ;get play sequence number
  982.         tst.b    (a2)
  983.         bmi.s    plr_noadvseq    ;Bxx sets nextblock to 0xff (= neg)
  984.         addq.w    #1,d0            ;advance sequence number
  985. plr_noadvseq:    cmp.w    msng_songlen(a4),d0    ;is this the highest seq number??
  986.         blt.s    plr_notagain        ;no.
  987.         moveq    #0,d0            ;yes: play song again
  988.         moveq    #0,d1            ;...forever
  989. plr_notagain:    move.b    d0,mmd_pseqnum+1(a6)    ;remember new playseq-#
  990.         lea    msng_playseq(a4),a0    ;offset of sequence table
  991.         move.b    0(a0,d0.w),d0        ;get number of the block
  992.     IFNE    CHECK
  993.         cmp.b    msng_numblocks+1(a4),d0    ;beyond last block??
  994.         blt.s    plr_nolstblk        ;no..
  995.         moveq    #0,d0            ;play block 0
  996.     ENDC
  997. plr_nolstblk:    move.b    d0,mmd_pblock+1(a6)    ;store pblock
  998. plr_nonewseq:    clr.b    (a2)            ;clear this if F00 set it
  999. plr_nochgblock:    move.w    d1,mmd_pline(a6)    ;set new pline
  1000.  
  1001.     IFNE    HOLD
  1002.         movea.l    mmd_blockarr(a6),a0
  1003.         move.w    mmd_pblock(a6),d0
  1004.         add.w    d0,d0
  1005.         add.w    d0,d0
  1006.         movea.l    0(a0,d0.w),a2
  1007.         move.b    (a2),d7            ;# of tracks
  1008.         move.w    mmd_pline(a6),d0    ;play line
  1009.         move.w    d0,d1
  1010.         add.w    d0,d0    ;d0 * 2
  1011.         add.w    d1,d0    ;+ d0 = d0 * 3
  1012.         mulu    d7,d0
  1013.         lea    2(a2,d0.w),a2
  1014.         move.b    msng_tempo2(a4),d3    ;interrupts/note
  1015.         lea    trackdataptrs(pc),a0
  1016.         subq.b    #1,d7
  1017. plr_chkhold:    movea.l    (a0)+,a1        ;track data
  1018.         tst.b    trk_noteoffcnt(a1)    ;hold??
  1019.         bmi.s    plr_holdend        ;no.
  1020.         move.b    (a2),d1            ;get the 1st byte..
  1021.         bne.s    plr_hold1
  1022.         move.b    1(a2),d1
  1023.         and.b    #$f0,d1
  1024.         beq.s    plr_holdend        ;don't hold
  1025.         bra.s    plr_hold2
  1026. plr_hold1:    and.b    #$3f,d1            ;note??
  1027.         beq.s    plr_hold2        ;no, cont hold..
  1028.         move.b    1(a2),d1
  1029.         and.b    #$0f,d1            ;get cmd
  1030.         subq.b    #3,d1            ;is there command 3 (slide)
  1031.         bne.s    plr_holdend        ;no -> end holding
  1032. plr_hold2:    add.b    d3,trk_noteoffcnt(a1)    ;continue holding...
  1033. plr_holdend:    addq.l    #3,a2        ;next note
  1034.         dbf    d7,plr_chkhold
  1035.     ENDC
  1036.         btst    #5,msng_flags(a4)    ;FLAG_STSLIDE??
  1037.         bne.w    plr_endfx        ;yes, no effects this time...
  1038.         moveq    #0,d3            ;counter = 0
  1039. nonewnote:
  1040. ;    *********************** This code produces the effects **
  1041.         moveq    #0,d7    ;clear track count
  1042.         moveq    #0,d6
  1043.         lea    trackdataptrs(pc),a2
  1044. plr_loop1:    movea.l    (a2)+,a5
  1045.         moveq    #0,d5
  1046.         moveq    #0,d4
  1047.         move.b    trk_cmd(a5),d6    ;get the fx number
  1048.         move.b    trk_cmdqual(a5),d4    ;and the last 2 #'s
  1049.     IFNE    MIDI
  1050.         tst.b    trk_prevmidin(a5)    ;first: is it MIDI??
  1051.         bne.w    midicmds
  1052.     ENDC
  1053.         cmp.w    #4,d7
  1054.         bge.w    endl    ;no non-MIDI effects in tracks 4 - 15
  1055.     IFNE    HOLD
  1056.         tst.b    trk_noteoffcnt(a5)
  1057.         bmi.s    plr_nowaitoff
  1058.         subq.b    #1,trk_noteoffcnt(a5)
  1059.         bpl.s    plr_nowaitoff
  1060.     IFNE    SYNTH
  1061.         tst.b    trk_synthtype(a5)    ;synth/hybrid??
  1062.         beq.s    plr_nosyndec
  1063.         move.b    trk_decay(a5),trk_volcmd+1(a5)    ;set volume command pointer
  1064.         clr.b    trk_volwait(a5)    ;abort WAI
  1065.         move.l    trk_synthptr(a5),d0
  1066.         bra.s    plr_gosynth
  1067.     ENDC
  1068. plr_nosyndec:    move.b    trk_decay(a5),trk_fadespd(a5)    ;set fade...
  1069.         bne.s    plr_nowaitoff    ;if > 0, don't stop sound
  1070.         bset    d7,d5
  1071.         move.w    d5,$dff096    ;shut DMA...
  1072.         moveq    #0,d5
  1073.     ENDC
  1074. plr_nowaitoff:
  1075.     IFNE    SYNTH
  1076.         move.l    trk_synthptr(a5),d0
  1077.         beq.s    plr_nosynth
  1078. plr_gosynth:    move.l    d0,a0
  1079.         bsr.w    synth_start
  1080.     ENDC
  1081. plr_nosynth:
  1082.     IFNE    HOLD
  1083.         move.b    trk_fadespd(a5),d0    ;fade??
  1084.         beq.s    plr_nofade    ;no.
  1085.         sub.b    d0,trk_prevvol(a5)
  1086.         bpl.s    plr_nofade2low
  1087.         clr.b    trk_prevvol(a5)
  1088.         clr.b    trk_fadespd(a5)        ;fade no more
  1089. plr_nofade2low:
  1090.     ENDC
  1091. plr_nofade:    movea.l    trk_audioaddr(a5),a1
  1092.         add.b    d6,d6    ;* 2
  1093.         move.w    fx_table(pc,d6.w),d0
  1094.         jmp    fxs(pc,d0.w)
  1095. fx_table:    dc.w    fx_00-fxs,fx_01-fxs,fx_02-fxs,fx_03-fxs,fx_04-fxs
  1096.         dc.w    fx_05-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs,fx_xx-fxs
  1097.         dc.w    fx_0a-fxs,fx_xx-fxs,fx_xx-fxs,fx_0d-fxs,fx_xx-fxs
  1098.         dc.w    fx_0f-fxs
  1099. fxs:
  1100. ;    **************************************** Effect 01 ******
  1101. fx_01:        sub.w    d4,trk_prevper(a5)    ;slide up
  1102.         move.w    trk_prevper(a5),d5
  1103.         cmp.w    #113,d5        ;too high?
  1104.         bge.s    fx_01_pushper
  1105.         move.w    #113,d5        ;too high
  1106.         move.w    d5,trk_prevper(a5)
  1107. fx_01_pushper    move.w    d5,ac_per(a1)
  1108.         bra.w    fx_xx
  1109. ;    **************************************** Effect 02 ******
  1110. fx_02:        add.w    d4,trk_prevper(a5)    ;slide down
  1111.         move.w    trk_prevper(a5),d5
  1112.         bra.s    fx_01_pushper
  1113. ;    **************************************** Effect 00 ******
  1114. fx_00:        tst.b    d4    ;both fxqualifiers are 0s: no arpeggio
  1115.         beq.w    fx_xx
  1116.         move.l    d3,d0
  1117.         divu    #3,d0
  1118.         swap    d0
  1119.         tst.w    d0
  1120.         bne.s    fx_arp12
  1121.         and.b    #$0f,d4
  1122.         add.b    (a5),d4
  1123.         bra.s    fx_doarp
  1124. fx_arp12:    subq.b    #1,d0
  1125.         bne.s    fx_arp2
  1126.         lsr.b    #4,d4
  1127.         add.b    (a5),d4
  1128.         bra.s    fx_doarp
  1129. fx_arp2:    move.b    (a5),d4
  1130. fx_doarp:    subq.b    #1,d4        ;-1 to make it 0 - 127
  1131.         add.b    msng_playtransp(a4),d4    ;add play transpose
  1132.         add.b    trk_stransp(a5),d4    ;add instrument transpose
  1133.         add.b    d4,d4        ;shift to make index for UWORD
  1134.         movea.l    trk_periodtbl(a5),a0
  1135.         move.w    0(a0,d4.w),ac_per(a1)
  1136.         bra.w    fx_xx
  1137. ;    **************************************** Effect 0D/0A ***
  1138. fx_0a:
  1139. fx_0d:        move.b    d4,d1
  1140.         move.b    trk_prevvol(a5),d0    ;move previous vol to d0
  1141.         and.b    #$f0,d1
  1142.         bne.s    crescendo
  1143.         sub.b    d4,d0    ;sub from prev. vol
  1144.         bpl.s    fx_0d_pushvol
  1145.         moveq    #0,d0    ;volumes under zero not accepted
  1146.         bra.s    fx_0d_pushvol
  1147. crescendo:    lsr.b    #4,d1
  1148.         add.b    d1,d0
  1149.         cmp.b    #64,d0
  1150.         ble.s    fx_0d_pushvol
  1151.         moveq    #64,d0
  1152. fx_0d_pushvol    move.b    d0,trk_prevvol(a5)
  1153.         move.b    d0,ac_vol+1(a1)
  1154.         bra.w    endl
  1155. ;    **************************************** Effect 05 ******
  1156. fx_05:        move.w    trk_prevper(a5),d5 ;this is very simple: get the old period
  1157.         cmp.b    #3,d3        ;and..
  1158.         bge.w    fx_05b        ;if counter < 3
  1159.         sub.w    d4,d5    ;subtract effect qualifier
  1160. fx_05b        move.w    d5,ac_per(a1)
  1161.         bra.w    fx_xx
  1162. ;    **************************************** Effect 03 ******
  1163. fx_03:        move.w    trk_porttrgper(a5),d0    ;d0 = target period
  1164.         beq.w    fx_xx        ;no target period specified
  1165.         move.w    trk_prevper(a5),d1    ;d1 = curr. period
  1166.         move.b    trk_prevportspd(a5),d4    ;get prev. speed
  1167.         cmp.w    d0,d1
  1168.         bhi.s    subper    ;curr. period > target period
  1169.         add.w    d4,d1    ;add the period
  1170.         cmp.w    d0,d1
  1171.         bge.s    targreached
  1172.         bra.s    targnreach
  1173. subper:        sub.w    d4,d1    ;subtract
  1174.         cmp.w    d0,d1    ;compare current period to target period
  1175.         bgt.s    targnreach
  1176. targreached:    move.w    trk_porttrgper(a5),d1 ;eventually push target period
  1177.         clr.w    trk_porttrgper(a5) ;now we can forget everything
  1178. targnreach:    move.w    d1,trk_prevper(a5)
  1179.         move.w    d1,ac_per(a1)
  1180.         bra.w    fx_xx
  1181. ;    **************************************** Effect 04 ******
  1182. fx_04:        tst.b    d4
  1183.         beq.s    nonvib
  1184.         move.b    d4,trk_vibrspdsz(a5)
  1185. nonvib:        move.b    trk_vibroffs(a5),d0
  1186.         lsr.b    #2,d0
  1187.         and.w    #$1f,d0
  1188.         moveq    #0,d1
  1189.         lea    sinetable(pc),a0
  1190.         move.b    0(a0,d0.w),d5
  1191.         ext.w    d5
  1192.         move.b    trk_vibrspdsz(a5),d0
  1193.         and.w    #$000f,d0
  1194.         muls    d0,d5
  1195.         asr.w    #5,d5
  1196.         add.w    trk_prevper(a5),d5
  1197.         move.b    trk_vibrspdsz(a5),d0
  1198.         lsr.b    #3,d0
  1199.         and.b    #$3e,d0
  1200.         add.b    d0,trk_vibroffs(a5)
  1201.         move.w    d5,ac_per(a1)
  1202.         bra.s    fx_xx
  1203. ;    **************************************** Effect 0F ******
  1204. fx_0f:        cmp.b    #$f1,d4
  1205.         bne.s    no0ff1
  1206.         cmp.b    #3,d3
  1207.         bne.w    fx_xx
  1208.         bra.s    playfxnote
  1209. no0ff1:        cmp.b    #$f2,d4
  1210.         bne.s    no0ff2
  1211.         cmp.b    #3,d3
  1212.         bne.w    fx_xx
  1213.         bra.s    playfxnote
  1214. no0ff2:        cmp.b    #$f3,d4
  1215.         bne.s    no0ff3
  1216.         move.b    d3,d0
  1217.         and.b    #2+4,d0        ;is 2 or 4
  1218.         beq.s    fx_xx
  1219. playfxnote:    move.w    d7,d0        ;track # to d0...
  1220.         moveq    #0,d1
  1221.         move.b    (a5),d1        ;get note # of previous note
  1222.         beq.s    fx_xx
  1223.         moveq    #0,d2
  1224.         move.b    trk_prevvol(a5),d2    ;get previous volume
  1225.         move.l    d3,-(sp)
  1226.         moveq    #0,d3
  1227.         move.b    trk_previnstr(a5),d3    ;and prev. sample #
  1228.         movea.l    trk_previnstra(a5),a3
  1229.         bsr    _PlayNote
  1230.         move.l    (sp)+,d3
  1231.         bra.s    endl
  1232. no0ff3:        cmp.b    #$f8,d4        ;f8 = filter off
  1233.         beq.s    plr_filteroff
  1234.         cmp.b    #$f9,d4        ;f9 = filter on
  1235.         bne.s    fx_xx
  1236.         bclr    #1,$bfe001
  1237.         bra.s    fx_xx
  1238. plr_filteroff:    bset    #1,$bfe001
  1239. ;    *********************************************************
  1240. fx_xx:        move.b    trk_prevvol(a5),ac_vol+1(a1)
  1241. endl:        addq.b    #1,d7    ;increment channel number
  1242.         cmp.w    numtracks(pc),d7    ;all channels done???
  1243.         blt.w    plr_loop1    ;not yet!!!
  1244. plr_endfx    bsr    _StartDMA    ;turn on DMA
  1245. plr_exit    movem.l    (sp)+,d2-d7/a2-a5
  1246.     IFNE    VBLANK
  1247.         moveq    #0,d0
  1248.     ENDC
  1249.         rts
  1250.  
  1251. _SetTempo:
  1252.     IFNE    CIAB
  1253.         cmp.b    #10,d0    ;If tempo <= 10, use SoundTracker tempo
  1254.         bhi.s    calctempo
  1255.         subq.b    #1,d0
  1256.         add.w    d0,d0
  1257.         move.w    sttempo+2(pc,d0.w),d1
  1258.         bra.s    pushtempo
  1259. calctempo:    move.l    timerdiv(pc),d1
  1260.         divu    d0,d1
  1261. pushtempo:    movea.l    craddr+4(pc),a0
  1262.         move.b    d1,(a0)        ;and set the CIA timer
  1263.         lsr.w    #8,d1
  1264.         movea.l    craddr+8(pc),a0
  1265.         move.b    d1,(a0)
  1266.     ENDC
  1267.         rts ;   vv-- These values are the SoundTracker tempos (approx.)
  1268. sttempo:    dc.w    $0f00
  1269.     IFNE    CIAB
  1270.         dc.w    2417,4833,7250,9666,12083,14500,16916,19332,21436,24163
  1271. timerdiv    dc.l    470000
  1272.     ENDC
  1273.  
  1274.     IFNE    MIDI
  1275. midicmds
  1276.     IFNE    HOLD
  1277.         tst.b    trk_noteoffcnt(a5)
  1278.         bmi.s    midi_nowaitoff
  1279.         subq.b    #1,trk_noteoffcnt(a5)
  1280.         bpl.s    midi_nowaitoff
  1281.         move.l    a5,a1
  1282.         move.b    trk_prevmidin(a5),d1
  1283.         beq.s    midi_nowaitoff    ;no note
  1284.         bsr.w    choff_midi
  1285. midi_nowaitoff:
  1286.     ENDC
  1287.         add.b    d6,d6    ;* 2
  1288.         move.w    midicmd_table(pc,d6.w),d0
  1289.         jmp    midifx(pc,d0.w)
  1290. midicmd_table:    dc.w    mfx_00-midifx,mfx_01-midifx,mfx_02-midifx,mfx_03-midifx,mfx_04-midifx
  1291.         dc.w    mfx_05-midifx,endl-midifx,endl-midifx,endl-midifx,endl-midifx
  1292.         dc.w    mfx_0a-midifx,endl-midifx,endl-midifx,mfx_0d-midifx,mfx_0e-midifx
  1293.         dc.w    mfx_0f-midifx
  1294. midifx        
  1295. mfx_01        lea    prevmidipbend(pc),a0
  1296.         moveq    #0,d1
  1297.         move.b    trk_prevmidich(a5),d1    ;get previous midi channel
  1298.         add.b    d1,d1        ;UWORD index
  1299.         tst.b    d4        ;x100??
  1300.         beq.s    resetpbend
  1301.         move.w    0(a0,d1.w),d0    ;get previous pitch bend
  1302.         lsl.w    #3,d4        ;multiply bend value by 8
  1303.         add.w    d4,d0
  1304.         cmp.w    #$3fff,d0
  1305.         bls.s    bendpitch
  1306.         move.w    #$3fff,d0
  1307. bendpitch:    move.w    d0,0(a0,d1.w)    ;save current pitch bend
  1308.         lsr.b    #1,d1        ;back to UBYTE
  1309.         or.b    #$e0,d1
  1310.         lea    noteondata(pc),a0
  1311.         move.b    d1,(a0)        ;midi command & channel
  1312.         move.b    d0,1(a0)    ;lower value
  1313.         and.b    #$7f,1(a0)    ;clear bit 7
  1314.         lsr.w    #7,d0
  1315.         and.b    #$7f,d0        ;clr bit 7
  1316.         move.b    d0,2(a0)    ;higher 7 bits
  1317.         moveq    #3,d0
  1318.         bsr.w    _AddMIDIData
  1319.         bra.w    endl
  1320.  
  1321. mfx_02        lea    prevmidipbend(pc),a0
  1322.         moveq    #0,d1
  1323.         move.b    trk_prevmidich(a5),d1
  1324.         add.b    d1,d1
  1325.         tst.b    d4
  1326.         beq.s    resetpbend    ;x200??
  1327.         move.w    0(a0,d1.w),d0
  1328.         lsl.w    #3,d4
  1329.         sub.w    d4,d0
  1330.         bpl.s    bendpitch    ;not under 0
  1331.         moveq    #0,d0
  1332.         bra.s    bendpitch
  1333. resetpbend:    tst.b    d3        ;d3 = counter (remember??)
  1334.         bne.w    endl
  1335.         move.w    #$2000,d0
  1336.         bra.s    bendpitch
  1337.  
  1338. mfx_03        tst.b    d3
  1339.         bne.w    endl
  1340.         lea    prevmidipbend(pc),a0
  1341.         moveq    #0,d1
  1342.         move.b    trk_prevmidich(a5),d1
  1343.         add.b    d1,d1
  1344.         move.b    d4,d0
  1345.         add.b    #128,d0
  1346.         lsl.w    #6,d0
  1347.         bra.s    bendpitch
  1348.  
  1349. mfx_0d        tst.b    d3
  1350.         bne.w    endl
  1351.         lea    noteondata+1(pc),a0    ;CHANNEL AFTERTOUCH
  1352.         move.b    d4,(a0)    ;value
  1353.         bmi.w    endl
  1354.         move.b    trk_prevmidich(a5),-(a0)
  1355.         or.b    #$d0,(a0)
  1356.         moveq    #2,d0
  1357.         bsr.w    _AddMIDIData
  1358.         bra.w    endl
  1359.  
  1360. mfx_0a        tst.b    d3
  1361.         bne.w    endl
  1362.         lea    noteondata+2(pc),a0    ;POLYPHONIC AFTERTOUCH
  1363.         and.b    #$7f,d4
  1364.         move.b    d4,(a0)
  1365.         move.b    trk_prevmidin(a5),-(a0)
  1366.         beq.w    endl
  1367.         move.b    trk_prevmidich(a5),-(a0)
  1368.         or.b    #$A0,(a0)
  1369.         moveq    #3,d0
  1370.         bsr.w    _AddMIDIData
  1371.         bra.w    endl
  1372.  
  1373. mfx_04        moveq    #$01,d0
  1374.         bra.s    pushctrldata
  1375.  
  1376. mfx_0e        moveq    #$0a,d0
  1377. pushctrldata    tst.b    d3        ;do it only once in a note
  1378.         bne.w    endl        ;(when counter = 0)
  1379.         lea    noteondata+2(pc),a0 ;push "control change" data,
  1380.         move.b    d4,(a0)        ;second databyte
  1381.         bmi.w    endl    ;I said 0 - $7f!!! (for future compability)
  1382.         move.b    d0,-(a0)    ;1st databyte
  1383.         move.b    trk_prevmidich(a5),-(a0)    ;MIDI channel
  1384.         or.b    #$b0,(a0)    ;command (B)
  1385.         moveq    #3,d0
  1386.         bsr.w    _AddMIDIData
  1387.         bra.w    endl
  1388.  
  1389. mfx_05        and.b    #$7f,d4        ;set contr. value of curr. MIDI ch.
  1390.         move.b    trk_prevmidich(a5),d6
  1391.         lea    midicontrnum(pc,d6.w),a0
  1392.         move.b    d4,(a0)
  1393.         bra.w    endl
  1394.  
  1395. mfx_0f        cmp.b    #$fa,d4        ;hold pedal ON
  1396.         bne.s    nomffa
  1397.         moveq    #$40,d0
  1398.         moveq    #$7f,d4
  1399.         bra.s    pushctrldata
  1400. nomffa        cmp.b    #$fb,d4        ;hold pedal OFF
  1401.         bne.s    nomffb
  1402.         moveq    #$40,d0
  1403.         moveq    #$00,d4
  1404.         bra.s    pushctrldata
  1405. nomffb        bra.w    fx_0f
  1406.  
  1407. mfx_00        tst.b    d4
  1408.         beq.w    endl
  1409.         and.b    #$7f,d4
  1410.         move.b    trk_prevmidich(a5),d6
  1411.         move.b    midicontrnum(pc,d6.w),d0
  1412.         bra.s    pushctrldata
  1413.  
  1414. midicontrnum    ds.b    16
  1415.  
  1416. _ResetMIDI:    movem.l    d2/a2,-(sp)
  1417.         lea    prevmidicpres(pc),a0
  1418.         clr.l    (a0)+    ;force presets to be set again
  1419.         clr.l    (a0)+    ;(clear prev. preset numbers)
  1420.         clr.l    (a0)+
  1421.         clr.l    (a0)
  1422.         clr.b    lastcmdbyte
  1423.         lea    midiresd(pc),a2
  1424.         move.b    #$e0,(a2)    ;reset pitchbenders & mod. wheel
  1425.         move.b    #$b0,3(a2)
  1426.         moveq    #15,d2
  1427. respbendl:    movea.l    a2,a0
  1428.         moveq    #6,d0
  1429.         bsr.w    _AddMIDIData
  1430.         addq.b    #1,(a2)
  1431.         addq.b    #1,3(a2)
  1432.         dbf    d2,respbendl
  1433.         lea    prevmidipbend(pc),a2
  1434.         moveq    #15,d2
  1435. resprevpbends:    move.w    #$2000,(a2)+
  1436.         dbf    d2,resprevpbends
  1437.         movem.l    (sp)+,d2/a2
  1438.         rts
  1439. midiresd:    dc.b    $e0,$00,$40,$b0,$01,$00
  1440.     ENDC
  1441.  
  1442. ; *************************************************************************
  1443. ; *************************************************************************
  1444. ; ***********          P U B L I C   F U N C T I O N S          ***********
  1445. ; *************************************************************************
  1446. ; *************************************************************************
  1447.  
  1448.     IFEQ    EASY
  1449.         xdef    _InitModule,_PlayModule,_PlayModule2
  1450.         xdef    _InitPlayer,_RemPlayer,_StopPlayer
  1451.         xdef    _SetTempo,_ContModule
  1452.     ENDC
  1453.     IFNE    EASY
  1454.  
  1455. ; This is the Reloc function, included only if EASY flag is set to 1.
  1456.  
  1457. reloci        move.l    24(a2),d0
  1458.         beq.s    xloci
  1459.         movea.l    d0,a0
  1460.         moveq   #0,d0
  1461.         move.b  787(a1),d0    ;number of samples
  1462.         subq.b  #1,d0
  1463. relocs:        bsr.s   relocentr
  1464.         move.l    -4(a0),d3    ;sample ptr
  1465.         beq.s    nosyn
  1466.         move.l    d3,a3
  1467.         tst.w    4(a3)
  1468.         bpl.s    nosyn        ;type >= 0
  1469.         move.w    20(a3),d2    ;number of waveforms
  1470.         lea    278(a3),a3    ;ptr to wf ptrs
  1471.         subq.w    #1,d2
  1472. relsyn:        add.l    d3,(a3)+
  1473.         dbf    d2,relsyn
  1474. nosyn:        dbf     d0,relocs
  1475. xloci        rts
  1476. norel        addq.l    #4,a0
  1477.         rts
  1478. relocentr:
  1479.         tst.l   (a0)
  1480.         beq.s   norel
  1481.         add.l   d1,(a0)+
  1482.         rts
  1483. _RelocModule:
  1484.         movem.l    a2-a3/d2-d3,-(sp)
  1485.         movea.l a0,a2
  1486.         move.l  a2,d1        ;d1 = ptr to start of module
  1487.         bsr.s    relocp
  1488.         movea.l 8(a2),a1
  1489.         bsr.s    reloci
  1490. rel_lp        bsr.s    relocb
  1491.         move.l    32(a2),d0    ;extension struct
  1492.         beq.s    rel_ex
  1493.         move.l    d0,a0
  1494.         bsr.s    relocentr    ;ptr to next module
  1495.         bsr.s    relocentr    ;InstrExt...
  1496.         addq.l    #4,a0        ;skip sizes of InstrExt
  1497. ; We reloc the pointers of MMD0exp, so anybody who needs them can easily
  1498. ; read them.
  1499.         bsr.s    relocentr    ;annotxt
  1500.         addq.l    #4,a0        ;annolen
  1501.         bsr.s    relocentr    ;InstrInfo
  1502.         addq.l    #8,a0
  1503.         bsr.s    relocentr    ;rgbtable (not useful for most people)
  1504.         addq.l    #4,a0        ;skip channelsplit
  1505.         bsr.s    relocentr    ;NotationInfo
  1506.         move.l    d0,a0
  1507.         move.l    (a0),d0
  1508.         beq.s    rel_ex
  1509.         move.l    d0,a2
  1510.         bsr.s    relocp
  1511.         movea.l 8(a2),a1
  1512.         bra.s    rel_lp
  1513. rel_ex        movem.l    (sp)+,d2-d3/a2-a3
  1514.         rts
  1515.  
  1516. relocb        move.l    16(a2),d0
  1517.         beq.s    xlocb
  1518.         movea.l    d0,a0
  1519.         move.w  504(a1),d0
  1520.         subq.b  #1,d0
  1521. rebl        bsr.s   relocentr
  1522.         dbf     d0,rebl
  1523. xlocb        rts
  1524.  
  1525. relocp        lea    8(a2),a0
  1526.         bsr.s    relocentr
  1527.         addq.l    #4,a0
  1528.         bsr.s    relocentr
  1529.         addq.l    #4,a0
  1530.         bsr.s    relocentr
  1531.         addq.l    #4,a0
  1532.         bra.s    relocentr
  1533.  
  1534.     ENDC
  1535.  
  1536.  
  1537. ; *************************************************************************
  1538. ; InitModule(a0 = module) -- extract expansion data etc.. from V3.xx module
  1539. ; *************************************************************************
  1540.  
  1541. _InitModule:    movem.l    a2-a3/d2,-(sp)
  1542.         move.l    a0,d0
  1543.         beq.s    IM_exit            ;0 => xit
  1544.     IFNE    RELVOL
  1545.         movea.l    mmd_songinfo(a0),a1    ;MMD0song
  1546.         move.b    msng_mastervol(a1),d0    ;d0 = mastervol
  1547.         ext.w    d0
  1548.         lea    msng_trkvol(a1),a1    ;a1 = trkvol
  1549.         lea    trackdataptrs(pc),a2
  1550.         moveq    #15,d1
  1551. IM_loop0    move.b    (a1)+,d2    ;get vol...
  1552.         ext.w    d2
  1553.         move.l    (a2)+,a3    ;pointer to track data
  1554.         mulu    d0,d2        ;mastervol * trackvol
  1555.         lsr.w    #4,d2
  1556.         move.w    d2,trk_trackvol(a3)
  1557.         dbf    d1,IM_loop0
  1558.     ENDC
  1559.         lea    holdvals(pc),a2
  1560.         movea.l    a0,a3
  1561.         move.l    mmd_expdata(a0),d0    ;expdata...
  1562.         beq.s    IM_clrhlddec        ;none here
  1563.         move.l    d0,a1
  1564.         move.l    4(a1),d0        ;exp_smp
  1565.         beq.s    IM_clrhlddec    ;again.. nothing
  1566.         move.l    d0,a0        ;InstrExt...
  1567.         move.w    8(a1),d2    ;# of entries
  1568.         beq.s    IM_clrhlddec
  1569.         subq.w    #1,d2        ;- 1 (for dbf)
  1570.         move.w    10(a1),d0    ;entry size
  1571.     IFNE    MIDI
  1572.         movea.l    mmd_songinfo(a3),a3    ;MMD0song
  1573.     ENDC
  1574. IM_loop1
  1575.     IFNE    MIDI
  1576.         cmp.w    #2,d0
  1577.         ble.s    IM_nsmnoff
  1578.         tst.b    2(a0)        ;suppress MIDI note off?
  1579.         beq.s    IM_nsmnoff
  1580.         bset    #7,inst_midich(a3)
  1581. IM_nsmnoff    addq.l    #8,a3        ;next instr
  1582.     ENDC
  1583.         move.b    1(a0),63(a2)    ;InstrExt.decay ->decay
  1584.         move.b    (a0),(a2)+    ;InstrExt.hold -> holdvals
  1585.         adda.w    d0,a0        ;ptr to next InstrExt
  1586.         dbf    d2,IM_loop1
  1587.         bra.s    IM_exit
  1588. IM_clrhlddec    moveq    #62,d0        ;no InstrExt => clear holdvals/decays
  1589. IM_loop2    clr.w    (a2)+
  1590.         dbf    d0,IM_loop2
  1591. IM_exit        movem.l    (sp)+,a2-a3/d2
  1592.         rts
  1593. ; *************************************************************************
  1594. ; InitPlayer() -- allocate interrupt, audio, serial port etc...
  1595. ; *************************************************************************
  1596. _InitPlayer:
  1597.     IFNE    MIDI
  1598.         bsr.w    _GetSerial
  1599.         tst.l    d0
  1600.         bne.s    IP_error
  1601.     ENDC
  1602.         bsr.w    _AudioInit
  1603.         tst.l    d0
  1604.         bne.s    IP_error
  1605.         moveq    #33,d0
  1606.         bsr.w    _SetTempo    ;set default tempo
  1607.         moveq    #0,d0
  1608.         rts
  1609. IP_error    bsr.s    _RemPlayer
  1610.         moveq    #-1,d0
  1611.         rts
  1612. ; *************************************************************************
  1613. ; RemPlayer() -- free interrupt, audio, serial port etc..
  1614. ; *************************************************************************
  1615. _RemPlayer:    move.b    _timeropen(pc),d0
  1616.         beq.s    RP_notimer    ;timer is not ours
  1617.         bsr.s    _StopPlayer
  1618. RP_notimer:    bsr.w    _AudioRem
  1619.     IFNE    MIDI
  1620.         bsr.w    _FreeSerial
  1621.     ENDC
  1622.         rts
  1623. ; *************************************************************************
  1624. ; StopPlayer() -- stop music
  1625. ; *************************************************************************
  1626. _StopPlayer:    move.b    _timeropen(pc),d0
  1627.         beq.s    SP_end        ;res. alloc fail.
  1628.     IFNE    CIAB
  1629.         movea.l    craddr(pc),a0
  1630.         bclr    #0,(a0)        ;stop timer
  1631.     ENDC
  1632.         move.l    _module(pc),d0
  1633.         beq.s    SP_nomod
  1634.         move.l    d0,a0
  1635.         clr.w    mmd_pstate(a0)
  1636.         clr.l    _module
  1637. SP_nomod
  1638.     IFNE    MIDI
  1639.         clr.b    lastcmdbyte
  1640.     ENDC
  1641.         bsr.w    SoundOff
  1642. SP_end        rts
  1643.  
  1644.  
  1645. _ContModule    move.b    _timeropen(pc),d0
  1646.         beq.s    SP_end
  1647.         movea.l    craddr(pc),a1
  1648.         bclr    #0,(a1)
  1649.         move.l    a0,-(sp)
  1650.         bsr.w    SoundOff
  1651.         move.l    (sp)+,a0
  1652.         moveq    #0,d0
  1653.         bra.s    contpoint
  1654. ; *************************************************************************
  1655. ; PlayModule(a0 = module)  -- initialize & play it!!
  1656. ; PlayModule2(a0 = module) -- play module (must be initialized)
  1657. ; *************************************************************************
  1658. _PlayModule:    st    d0
  1659. contpoint    movem.l    a0/d0,-(sp)
  1660.         bsr    _InitModule
  1661.         movem.l    (sp)+,a0/d0
  1662. _PlayModule2:    move.b    _timeropen(pc),d1
  1663.         beq.s    SP_end        ;resource allocation failure
  1664.         move.l    a0,d1
  1665.         beq.s    SP_end        ;module failure
  1666.     IFNE    CIAB
  1667.         movea.l    craddr(pc),a1
  1668.         bclr    #0,(a1)        ;stop timer...
  1669.     ENDC
  1670.         clr.l    _module
  1671.     IFNE    MIDI
  1672.         clr.b    lastcmdbyte
  1673.     ENDC
  1674.         move.w    _modnum,d1
  1675.         beq.s    PM_modfound
  1676. PM_nextmod    tst.l    mmd_expdata(a0)
  1677.         beq.s    PM_modfound
  1678.         move.l    mmd_expdata(a0),a1
  1679.         tst.l    (a1)
  1680.         beq.s    PM_modfound        ;no more modules here!
  1681.         move.l    (a1),a0
  1682.         subq.w    #1,d1
  1683.         bgt.s    PM_nextmod
  1684. PM_modfound    movea.l    mmd_songinfo(a0),a1        ;song
  1685.         move.b    msng_tempo2(a1),mmd_counter(a0)    ;init counter
  1686.         btst    #0,msng_flags(a1)
  1687.         bne.s    PM_filon
  1688.         bset    #1,$bfe001
  1689.         bra.s    PM_filset
  1690. PM_filon    bclr    #1,$bfe001
  1691. PM_filset    tst.b    d0
  1692.         beq.s    PM_noclr
  1693.         clr.l    mmd_pline(a0)
  1694. PM_noclr    move.w    mmd_pseqnum(a0),d1
  1695.         add.w    #msng_playseq,d1
  1696.         move.b    0(a1,d1.w),d1        ;get first playseq entry
  1697.         move.b    d1,mmd_pblock+1(a0)
  1698.         move.w    #-1,mmd_pstate(a0)
  1699.         move.l    a0,_module
  1700.     IFNE    CIAB
  1701.         move.w    msng_deftempo(a1),d0    ;get default tempo
  1702.         movea.l    craddr(pc),a1
  1703.         bsr.w    _SetTempo    ;set default tempo
  1704.         bset    #0,(a1)        ;start timer => PLAY!!
  1705.     ENDC
  1706. PM_end        rts
  1707. ; *************************************************************************
  1708.  
  1709. _AudioInit:    movem.l    a4/a6/d2-d3,-(sp)
  1710.         moveq    #0,d2
  1711.         movea.l    4,a6
  1712. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ alloc signal bit
  1713.     IFNE    AUDDEV
  1714.         addq.l    #1,d2
  1715.         moveq    #-1,d0
  1716.         jsr    -$14a(a6)    ;AllocSignal()
  1717.         tst.b    d0
  1718.         bmi.w    initerr
  1719.         move.b    d0,sigbitnum
  1720. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ prepare IORequest
  1721.         lea    allocport(pc),a1
  1722.         move.b    d0,15(a1)    ;set mp_SigBit
  1723.         move.l    a1,-(sp)
  1724.         suba.l    a1,a1
  1725.         jsr    -$126(a6)    ;FindTask(0)
  1726.         move.l    (sp)+,a1
  1727.         move.l    d0,16(a1)    ;set mp_SigTask
  1728.         lea    reqlist(pc),a0
  1729.         move.l    a0,(a0)        ;NEWLIST begins...
  1730.         addq.l    #4,(a0)
  1731.         clr.l    4(a0)
  1732.         move.l    a0,8(a0)    ;NEWLIST ends...
  1733. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open audio.device
  1734.         addq.l    #1,d2
  1735.         lea    allocreq(pc),a1
  1736.         lea    audiodevname(pc),a0
  1737.         moveq    #0,d0
  1738.         moveq    #0,d1
  1739.         jsr    -$1bc(a6)    ;OpenDevice()
  1740.         tst.b    d0
  1741.         bne.w    initerr
  1742.         st.b    audiodevopen
  1743. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ open ciaa.resource
  1744.         addq.l    #1,d2
  1745.     ENDC
  1746.     IFNE    CIAB
  1747.         cmp.b    #50,$212(a6)    ;ExecBase->VBlankFrequency
  1748.         beq.s    init_pal
  1749.         move.l    #474326,timerdiv ;Assume that CIA freq is 715 909 Hz
  1750. init_pal    moveq    #0,d0
  1751.         lea    ciabname(pc),a1
  1752.         jsr    -$1f2(a6)    ;OpenResource()
  1753.         tst.l    d0
  1754.         beq.s    initerr
  1755.         move.l    d0,_ciaresource
  1756. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ attach interrupt
  1757.         addq.l    #1,d2
  1758.         moveq    #2,d3
  1759.         lea    craddr(pc),a4
  1760.         move.l    #$bfdf00,(a4)+    ;Initialize Timer B addresses
  1761.         move.l    #$bfd600,(a4)+
  1762.         move.l    #$bfd700,(a4)
  1763.         move.l    d0,a6
  1764.         lea    timerinterrupt(pc),a1    ;Attempt to get timer B
  1765.         moveq    #1,d0    ;Bit number 1: Timer B
  1766.         jsr    -$6(a6)    ;AddICRVector
  1767.         tst.l    d0
  1768.         beq.s    gotTimerB        ;succeeded!!
  1769.         moveq    #1,d3
  1770.         lea    timerinterrupt(pc),a1    ;no. Get timer A then...
  1771.         moveq    #0,d0    ;Bit number 0: Timer A
  1772.         jsr    -$6(a6)
  1773.         tst.l    d0
  1774.         bne.s    initerr
  1775.         move.l    #$bfd500,(a4)        ;Set Timer A addresses
  1776.         move.l    #$bfd400,-(a4)
  1777.         move.l    #$bfde00,-(a4)
  1778. gotTimerB:    movea.l    craddr(pc),a0    ;get Control Register address
  1779.         and.b    #%10000000,(a0) ;clear CtrlReg bits 0 - 6
  1780.         move.b    d3,_timeropen    ;d3: 1 = TimerA 2 = TimerB
  1781.     ENDC
  1782.     IFNE    VBLANK
  1783.         moveq    #5,d0        ;INTB_VERTB
  1784.         lea    timerinterrupt(pc),a1
  1785.         jsr    -$a8(a6)    ;AddIntServer
  1786.         st    _timeropen
  1787.     ENDC
  1788.         moveq    #0,d0
  1789. initret:    movem.l    (sp)+,a4/a6/d2-d3
  1790.         rts
  1791. initerr:    move.l    d2,d0
  1792.         bra.s    initret
  1793.  
  1794. _AudioRem:    move.l    a6,-(sp)
  1795.         moveq    #0,d0
  1796.         move.b    _timeropen(pc),d0
  1797.         beq.s    rem1
  1798. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ remove interrupt
  1799.         clr.b    _timeropen
  1800.     IFNE    CIAB
  1801.         move.l    _ciaresource,a6
  1802.         lea    timerinterrupt(pc),a1
  1803.         subq.b    #1,d0
  1804.         jsr    -$c(a6)        ;RemICRVector
  1805.     ENDC
  1806.     IFNE    VBLANK
  1807.         movea.l    4,a6
  1808.         lea    timerinterrupt(pc),a1
  1809.         moveq    #5,d0
  1810.         jsr    -$ae(a6)    ;RemIntServer
  1811.     ENDC
  1812. rem1:
  1813.     IFNE    AUDDEV
  1814.         movea.l    4,a6
  1815.         tst.b    audiodevopen
  1816.         beq.s    rem2
  1817.         move.w    #$000f,$dff096    ;stop audio DMA
  1818. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ close audio.device
  1819.         lea    allocreq(pc),a1
  1820.         jsr    -$1c2(a6)    ;CloseDevice()
  1821.         clr.b    audiodevopen
  1822. rem2:        moveq    #0,d0
  1823.         move.b    sigbitnum(pc),d0
  1824.         bmi.s    rem3
  1825. ;    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ free signal bit
  1826.         jsr    -$150(a6)    ;FreeSignal()
  1827.         st    sigbitnum
  1828.     ENDC
  1829. rem3:        move.l    (sp)+,a6
  1830.         rts
  1831.  
  1832.     IFNE    MIDI
  1833. _GetSerial:    move.l    a6,-(sp)    ;Get serial port for MIDI
  1834.         bsr.s    GetSer2
  1835.         tst.l    d0        ;got the port??
  1836.         beq.s    rgser        ;yes
  1837.         movea.l    4,a6        ;no..try to flush serial.device:
  1838.         jsr    -$84(a6)        ;Forbid
  1839.         lea    $15e(a6),a0        ;ExecBase->DeviceList
  1840.         lea    serdev(pc),a1        ;"serial.device"
  1841.         jsr    -$114(a6)        ;FindName
  1842.         tst.l    d0
  1843.         beq.s    serdnotf        ;no serial.device!!
  1844.         move.l    d0,a1
  1845.         jsr    -$1b6(a6)        ;RemDevice
  1846. serdnotf:    jsr    -$8a(a6)        ;and Permit
  1847.         bsr.s    GetSer2        ;now try it again...
  1848. rgser:        move.l    (sp)+,a6
  1849.         rts
  1850.  
  1851. GetSer2:    movea.l    4,a6
  1852.         moveq    #0,d0
  1853.         lea    miscresname(pc),a1
  1854.         jsr    -$1f2(a6)    ;OpenResource()
  1855.         move.l    d0,miscresbase
  1856.         tst.l    d0
  1857.         beq.s    gserror
  1858.         move.l    d0,a6
  1859.         lea    medname(pc),a1
  1860.         moveq    #0,d0        ;serial port
  1861.         jsr    -$6(a6)        ;AllocMiscResource()
  1862.         tst.l    d0
  1863.         bne.s    gserror
  1864.         moveq    #0,d0        ;TBE
  1865.         lea    serinterrupt(pc),a1
  1866.         move.l    4,a6
  1867.         jsr    -$a2(a6)    ;SetIntVector()
  1868.         move.l    d0,prevtbe
  1869.         move.w    #$8001,$dff09a    ;TBE on!!
  1870.         move.w    #114,$dff032    ;set baud rate (SERPER)
  1871.         st.b    serportalloc
  1872.         moveq    #0,d0
  1873.         rts
  1874. gserror:    moveq    #-1,d0
  1875.         rts
  1876.  
  1877.  
  1878. _FreeSerial:    move.l    a6,-(sp)
  1879.         tst.l    miscresbase
  1880.         beq.s    retfs
  1881.         tst.b    serportalloc
  1882.         beq.s    retfs
  1883.         movea.l    4,a6
  1884.         tst.b    $126(a6)    ;interrupts disabled?
  1885.         bge.s    fs_skipwait    ;yes, can't busy loop...
  1886. fs_waitempty    move.b    buffempty(pc),d0
  1887.         beq.s    fs_waitempty
  1888. fs_skipwait    move.w    #$0001,$dff09a    ;disable TBE
  1889.         move.l    prevtbe(pc),a1
  1890.         moveq    #0,d0
  1891.         jsr    -$a2(a6)    ;SetIntVector()
  1892. fs_noptbe    movea.l    miscresbase(pc),a6
  1893.         moveq    #0,d0        ;serial port
  1894.         jsr    -$c(a6)        ;FreeMiscResource()
  1895.         clr.b    serportalloc
  1896.         clr.b    lastcmdbyte
  1897. retfs:        move.l    (sp)+,a6
  1898.         rts
  1899.  
  1900. prevtbe:    dc.l    0
  1901.  
  1902. SerIntHandler:    move.w    #$4000,$9a(a0)    ;disable...
  1903.         addq.b    #1,$126(a6)    (Interrupts are enabled anyway...)
  1904.         move.w    #1,$9c(a0)    ;clear intreq bit
  1905.         move.b    8(a1),d0    ;bytesinbuff
  1906.         beq.s    sih_buffe    ;buffer empty
  1907.         movea.l    4(a1),a5    ;get buffer read pointer
  1908.         move.w    #$100,d1    ;Stop bit
  1909.         move.b    (a5)+,d1    ;get byte
  1910.         move.w    d1,$30(a0)    ;and push it out!! (SERDAT)
  1911.         cmpa.l    a1,a5        ;shall we reset ptr??
  1912.         bne.s    norrbuffptr    ;not yet..
  1913.         lea    sendbuffer(pc),a5
  1914. norrbuffptr:    subq.b    #1,d0        ;one less bytes in buffer
  1915.         move.b    d0,8(a1)    ;remember it
  1916.         move.l    a5,4(a1)    ;push new read pointer back
  1917. exsih:        subq.b    #1,$126(a6)
  1918.         bge.s    exsih0
  1919.         move.w    #$c000,$9a(a0)
  1920. exsih0:        rts
  1921. sih_buffe    st    9(a1)
  1922.         bra.s    exsih
  1923.  
  1924. _AddMIDIData:    tst.b    serportalloc
  1925.         beq.s    retamd
  1926.         movem.l    a2/a6,-(sp)
  1927.         movea.l    4,a6
  1928.         move.w    #$4000,$dff09a    ;Disable interrupts
  1929.         addq.b    #1,$126(a6)    ;ExecBase->IDNestCnt
  1930.         lea    buffptr(pc),a2    ;end of buffer (ptr)
  1931.         tst.b    9(a2)
  1932.         beq.s    noTBEreq
  1933.         clr.b    9(a2)
  1934.         move.w    #$8001,$dff09c    ;request TBE
  1935. noTBEreq    movea.l    (a2),a1        ;buffer pointer
  1936. adddataloop:    move.b    (a0)+,d1    ;get byte
  1937.         bpl.s    norscheck    ;this isn't a status byte
  1938.         cmp.b    #$ef,d1        ;forget system messages
  1939.         bhi.s    norscheck
  1940.         cmp.b    lastcmdbyte(pc),d1 ;same as previos status byte??
  1941.         beq.s    samesb        ;yes, skip
  1942.         move.b    d1,10(a2)    ;no, don't skip but remember!!
  1943. norscheck:    move.b    d1,(a1)+    ;push it to midi send buffer
  1944.         addq.b    #1,8(a2)
  1945. samesb:        cmpa.l    a2,a1    ;end of buffer??
  1946.         bne.s    noresbuffptr    ;no, no!!
  1947.         lea    sendbuffer(pc),a1 ;better reset it to avoid trashing
  1948. noresbuffptr:    subq.b    #1,d0
  1949.         bne.s    adddataloop
  1950.         move.l    a1,(a2)        ;push new buffer ptr back
  1951.         subq.b    #1,$126(a6)
  1952.         bge.s    retamd1
  1953.         move.w    #$c000,$dff09a    ;enable interrupts again
  1954. retamd1        movem.l    (sp)+,a2/a6
  1955. retamd        rts
  1956. sendbuffer    ds.b    128
  1957. buffptr        dc.l    sendbuffer
  1958. readbuffptr    dc.l    sendbuffer
  1959. bytesinbuff    dc.b    0
  1960. buffempty    dc.b    -1
  1961. lastcmdbyte    dc.b    0
  1962.     ENDC
  1963.     IFNE    AUDDEV
  1964. sigbitnum    dc.b    -1
  1965.     ENDC
  1966.         EVEN
  1967.     IFNE    AUDDEV
  1968. audiodevopen    dc.b    0
  1969.     ENDC
  1970. serportalloc    dc.b    0
  1971. _timeropen    dc.b    0
  1972.         even
  1973.     IFNE    MIDI
  1974. preschgdata    dc.w    0
  1975. noteondata    dc.l    0
  1976. miscresbase    dc.l    0
  1977.     ENDC
  1978. dmaonmsk    dc.w    0
  1979.     IFNE    MIDI
  1980. bytesinnotebuff    dc.w    0
  1981. noteonbuff    ds.b    18*3
  1982.     ENDC
  1983.         even
  1984.     IFNE    CIAB
  1985. _ciaresource    dc.l    0
  1986. craddr        dc.l    0
  1987.         dc.l    0    ;tloaddr
  1988.         dc.l    0    ;thiaddr
  1989.     ENDC
  1990. _module:    dc.l    0
  1991. timerinterrupt    dc.w    0,0,0,0,0
  1992.         dc.l    timerintname,serportalloc,_IntHandler
  1993.     IFNE    MIDI
  1994. serinterrupt    dc.w    0,0,0,0,0
  1995.         dc.l    serintname,buffptr,SerIntHandler
  1996.     ENDC
  1997.     IFNE    AUDDEV
  1998. allocport    dc.l    0,0    ;succ, pred
  1999.         dc.b    4,0    ;NT_MSGPORT
  2000.         dc.l    0    ;name
  2001.         dc.b    0,0    ;flags = PA_SIGNAL
  2002.         dc.l    0    ;task
  2003. reqlist        dc.l    0,0,0    ;list head, tail and tailpred
  2004.         dc.b    5,0
  2005. allocreq    dc.l    0,0
  2006.         dc.b    5,127    ;NT_MESSAGE, use maximum priority (127)
  2007.         dc.l    0,allocport    ;name, replyport
  2008.         dc.w    68        ;length
  2009.         dc.l    0    ;io_Device
  2010.         dc.l    0    ;io_Unit
  2011.         dc.w    0    ;io_Command
  2012.         dc.b    0,0    ;io_Flags, io_Error
  2013.         dc.w    0    ;ioa_AllocKey
  2014.         dc.l    sttempo    ;ioa_Data
  2015.         dc.l    1    ;ioa_Length
  2016.         dc.w    0,0,0    ;ioa_Period, Volume, Cycles
  2017.         dc.w    0,0,0,0,0,0,0,0,0,0    ;ioa_WriteMsg
  2018. audiodevname    dc.b    'audio.device',0
  2019.     ENDC
  2020.     IFNE    CIAB
  2021. ciabname    dc.b    'ciab.resource',0
  2022.     ENDC
  2023. timerintname    dc.b    'MEDTimerInterrupt',0
  2024.     IFNE    MIDI
  2025. serintname    dc.b    'MEDSerialInterrupt',0
  2026. miscresname    dc.b    'misc.resource',0
  2027. serdev        dc.b    'serial.device',0
  2028. medname        dc.b    'MED modplayer',0 ;yeah, our name
  2029.     ENDC
  2030.  
  2031.     IFNE    SYNTH
  2032. _synthper:    dc.w 3424,3232,3048,2880,2712,2560,2416,2280,2152,2032
  2033.         dc.w 1920,1812,1712,1616,1524,1440,1356,1280,1208,1140
  2034.         dc.w 1076,1016,960,906
  2035.     ENDC
  2036. _periods:    dc.w 856,808,762,720,678,640,604,570,538,508,480,453
  2037.         dc.w 428,404,381,360,339,320,302,285,269,254,240,226
  2038.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  2039.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  2040.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  2041.         dc.w 214,202,190,180,170,160,151,143,135,127,120,113
  2042.  
  2043. holdvals:    ds.b 63
  2044. decays:        ds.b 63
  2045.  
  2046.     IFND    __G2
  2047.         section "datachip",data,chip ;for A68k
  2048.     ENDC
  2049.     IFD    __G2
  2050.         section "datachip",data_c ;this is for Devpac 2
  2051.     ENDC
  2052.         xdef    _modnum
  2053.     IFNE    EASY
  2054. easymod        incbin    "module"    ;<<<<< MODULE NAME HERE!
  2055.     ENDC
  2056. _chipzero:    dc.l    0
  2057. _modnum:    dc.w    0    ;number of module to play
  2058.  
  2059. ; the track-data structure definition:
  2060. trk_prevnote    equ    0    ;previous note number
  2061. trk_previnstr    equ    1    ;previous instrument number
  2062. trk_prevvol    equ    2    ;previous volume
  2063. trk_prevmidich    equ    3    ;previous MIDI channel
  2064. trk_cmd        equ    4    ;command (the 3rd number from right)
  2065. trk_cmdqual    equ    5    ;command qualifier (infobyte, databyte..)
  2066. trk_prevmidin    equ    6    ;previous MIDI note
  2067. trk_noteoffcnt    equ    7    ;note-off counter (hold)
  2068. trk_inithold    equ    8    ;default hold for this instrument
  2069. trk_initdecay    equ    9    ;default decay for....
  2070. trk_stransp    equ    10    ;instrument transpose
  2071. trk_pad0    equ    11
  2072. trk_previnstra    equ    12    ;address of the previous instrument data
  2073. trk_trackvol    equ    16
  2074. ;    the following data only on tracks 0 - 3
  2075. trk_prevper    equ    18    ;previous period
  2076. trk_audioaddr    equ    20    ;hardware audio channel base address
  2077. trk_sampleptr    equ    24    ;pointer to sample
  2078. trk_samplelen    equ    28    ;length (>> 1)
  2079. trk_porttrgper    equ    30    ;portamento (cmd 3) target period
  2080. trk_vibroffs    equ    32    ;vibrato table offset
  2081. trk_vibrspdsz    equ    33    ;vibrato speed/size (cmd 4 qualifier)
  2082. trk_synthptr    equ    34    ;pointer to synthetic/hybrid instrument
  2083. trk_arpgoffs    equ    38    ;SYNTH: current arpeggio offset
  2084. trk_arpsoffs    equ    40    ;SYNTH: arpeggio restart offset
  2085. trk_volxcnt    equ    42    ;SYNTH: volume execute counter
  2086. trk_wfxcnt    equ    43    ;SYNTH: waveform execute counter
  2087. trk_volcmd    equ    44    ;SYNTH: volume command pointer
  2088. trk_wfcmd    equ    46    ;SYNTH: waveform command pointer
  2089. trk_volwait    equ    48    ;SYNTH: counter for WAI (volume list)
  2090. trk_wfwait    equ    49    ;SYNTH: counter for WAI (waveform list)
  2091. trk_synthvibspd    equ    50    ;SYNTH: vibrato speed
  2092. trk_wfchgspd    equ    52    ;SYNTH: period change
  2093. trk_perchg    equ    54    ;SYNTH: curr. period change from trk_prevper
  2094. trk_envptr    equ    56    ;SYNTH: envelope waveform pointer
  2095. trk_synvibdep    equ    60    ;SYNTH: vibrato depth
  2096. trk_synvibwf    equ    62    ;SYNTH: vibrato waveform
  2097. trk_synviboffs    equ    66    ;SYNTH: vibrato pointer
  2098. trk_initvolxspd    equ    68    ;SYNTH: volume execute speed
  2099. trk_initwfxspd    equ    69    ;SYNTH: waveform execute speed
  2100. trk_volchgspd    equ    70    ;SYNTH: volume change
  2101. trk_prevnote2    equ    71    ;SYNTH: previous note
  2102. trk_synvol    equ    72    ;SYNTH: current volume
  2103. trk_synthtype    equ    73    ;>0 = synth, -1 = hybrid, 0 = no synth
  2104. trk_periodtbl    equ    74    ;pointer to period table
  2105. trk_prevportspd    equ    78    ;portamento (cmd 3) speed
  2106. trk_decay    equ    80    ;decay
  2107. trk_fadespd    equ    81    ;decay speed
  2108. trk_envrestart    equ    82    ;SYNTH: envelope waveform restart point
  2109. trk_envcount    equ    86    ;SYNTH: envelope counter
  2110. trk_split    equ    87    ;0 = this channel not splitted (OctaMED V2)
  2111.         end
  2112.